/*=============================================================================
  D3DSystem.cpp : D3D initialization / system functions.
  Copyright (c) 2001 Crytek Studios. All Rights Reserved.

  Revision history:
    * Created by Honich Andrey

=============================================================================*/

#include "StdAfx.h"
#include "DriverD3D.h"
#include <IHardwareMouse.h>
#include "D3DStereo.h"
#include "D3DLightPropagationVolume.h"
#include "D3DPostProcess.h"
#include "D3DREBreakableGlassBuffer.h"

//#ifdef CAFE
//#include "RenderToDRC.h"
//#endif

#if defined(DIRECT3D9)
	#define WINDOWNAME_GFXVERSION " [DIRECT3D9]"
#elif defined(DIRECT3D10)
	#define WINDOWNAME_GFXVERSION " [DIRECT3D10]"
#else
	#define WINDOWNAME_GFXVERSION ""
#endif

#ifdef USE_NV_API
	#include "../Common/ATI/atimgpud.h"					// ATI multicpu detection
	#include "../Common/NVAPI/nvapi.h"					// NVAPI multicpu support api
  #pragma message (">>> include lib: NVAPI")
  #ifdef WIN64
    #pragma comment(lib,"nvapi64.lib")
  #else // WIN64
    #pragma comment(lib,"nvapi.lib")
  #endif // WIN64
#endif

#if defined(DIRECT3D9) && (defined(WIN32) || defined(WIN64))
#	include <ddraw.h>
#endif

#if defined(WIN32) || defined(WIN64)
#include <dxerr.h>
#endif

#	define PUREFMT(D3dFmt) (D3dFmt)


  UINT WINAPI GetD3D9ColorBits( D3DFORMAT fmt )
  {
    switch( PUREFMT(fmt) )
    {
#if !defined(XENON)
    case PUREFMT(D3DFMT_R8G8B8):
      return 24;
    case PUREFMT(D3DFMT_R3G3B2):
      return 8;
    case PUREFMT(D3DFMT_A8R3G3B2):
      return 16;
#endif
    case PUREFMT(D3DFMT_A8R8G8B8):
      return 32;

#if !defined(XENON)	// dupicate formats
		case PUREFMT(D3DFMT_X8R8G8B8):
      return 32;
		case PUREFMT(D3DFMT_A1R5G5B5):
			return 16;
		case PUREFMT(D3DFMT_X4R4G4B4):
			return 16;
		case PUREFMT(D3DFMT_A8B8G8R8):
			return 32;
		case PUREFMT(D3DFMT_A2R10G10B10):
			return 32;
		case PUREFMT(D3DFMT_L8):
			return 8;
		case PUREFMT(D3DFMT_V8U8):
			return 16;
		case PUREFMT(D3DFMT_X8L8V8U8):
		case PUREFMT(D3DFMT_Q8W8V8U8):
			return 32;
		case PUREFMT(D3DFMT_V16U16):
			return 32;
		case PUREFMT(D3DFMT_DF16):
			return 16;
		case PUREFMT(D3DFMT_DF24):
			return 24;
#endif

    case PUREFMT(D3DFMT_R5G6B5):
      return 16;
    case PUREFMT(D3DFMT_X1R5G5B5):
      return 16;
    case PUREFMT(D3DFMT_A4R4G4B4):
      return 16;

    case PUREFMT(D3DFMT_A2B10G10R10):
      return 32;
    case PUREFMT(D3DFMT_A16B16G16R16):
      return 64;

    case PUREFMT(D3DFMT_A16B16G16R16F):
      return 64;
    case PUREFMT(D3DFMT_A32B32G32R32F):
      return 128;
    case PUREFMT(D3DFMT_G16R16):
      return 32;
    case PUREFMT(D3DFMT_G16R16F):
      return 32;
    case PUREFMT(D3DFMT_R16F):
      return 16;
    case PUREFMT(D3DFMT_R32F):
      return 32;
    case PUREFMT(D3DFMT_A8):
      return 8;
    case PUREFMT(D3DFMT_A8L8):
      return 16;
    case PUREFMT(D3DFMT_L6V5U5):
      return 16;
    case PUREFMT(D3DFMT_DXT1):
      return 8;
    case PUREFMT(D3DFMT_DXT3):
      return 16;
    case PUREFMT(D3DFMT_DXT5):
      return 16;
    case PUREFMT(D3DFMT_3DC):
      return 16;
    case PUREFMT(D3DFMT_D24S8):
      return 32;
    case PUREFMT(D3DFMT_D24FS8):
      return 32;
    case PUREFMT(D3DFMT_D16):
      return 16;
    case PUREFMT(D3DFMT_NULL):
      return 8; //hack

    default:
      assert(0);
      return 0;
    }
  }

  int GetD3D9ColorBytes( const D3DFORMAT format )
  {
    switch( PUREFMT(format) )
    {
      // 1 byte formats
#if !defined(XENON)
    case PUREFMT(D3DFMT_R3G3B2):
#endif
    case PUREFMT(D3DFMT_A8):
#if !defined(XENON)
		case PUREFMT(D3DFMT_L8):
#endif
			{
        return( 1 );
      }	
      // 2 byte formats
    case PUREFMT(D3DFMT_R5G6B5):
    case PUREFMT(D3DFMT_X1R5G5B5):
    case PUREFMT(D3DFMT_A4R4G4B4):

#if !defined(XENON)	// duplicated formats for Xenon
		case PUREFMT(D3DFMT_A1R5G5B5):
		case PUREFMT(D3DFMT_X4R4G4B4):
		case PUREFMT(D3DFMT_V8U8):
		case PUREFMT(D3DFMT_L16):
#endif

#if !defined(XENON)
    case PUREFMT(D3DFMT_A8R3G3B2):
    case PUREFMT(D3DFMT_D15S1):
#endif
    case PUREFMT(D3DFMT_A8L8):
    case PUREFMT(D3DFMT_L6V5U5):
    case PUREFMT(D3DFMT_D16):
    case PUREFMT(D3DFMT_INDEX16):
    case PUREFMT(D3DFMT_R16F):
      {
        return( 2 );
      }
      // 3 byte formats
#if !defined(XENON)
    case PUREFMT(D3DFMT_R8G8B8):
      {
        return( 3 );
      }
#endif
      // 4 byte formats
    case PUREFMT(D3DFMT_A8R8G8B8):

#if !defined(XENON)	// duplicated formats for Xenon
		case PUREFMT(D3DFMT_X8R8G8B8):
		case PUREFMT(D3DFMT_A8B8G8R8):
		case PUREFMT(D3DFMT_X8B8G8R8):
		case PUREFMT(D3DFMT_A2R10G10B10):
		case PUREFMT(D3DFMT_X8L8V8U8):
		case PUREFMT(D3DFMT_Q8W8V8U8):
		case PUREFMT(D3DFMT_V16U16):
		case PUREFMT(D3DFMT_A2W10V10U10):	
		case PUREFMT(D3DFMT_D24X8):
		case PUREFMT(D3DFMT_INDEX32):
#endif






    case PUREFMT(D3DFMT_A2B10G10R10):
    case PUREFMT(D3DFMT_G16R16):
    case PUREFMT(D3DFMT_D32):
    case PUREFMT(D3DFMT_D24S8):
    case PUREFMT(D3DFMT_D24FS8):
    case PUREFMT(D3DFMT_G16R16F):
    case PUREFMT(D3DFMT_R32F):
      {
        return( 4 );
      }
      // 8 byte formats




#if !defined(XENON)	// duplicated formats for Xenon
		case PUREFMT(D3DFMT_Q16W16V16U16):
#endif

    case PUREFMT(D3DFMT_A16B16G16R16):
    case PUREFMT(D3DFMT_A16B16G16R16F):
    case PUREFMT(D3DFMT_G32R32F):
      {
        return( 8 );
      }
      // 16 byte formats
    case PUREFMT(D3DFMT_A32B32G32R32F):
      {
        return( 16 );
      }		
      // all others
    default:
      {
        assert( !"Unknown or unsupported D3DFORMAT!" );
        return( 0 );
      }
    }
  }

  int GetD3D9NumSamples( const D3DMULTISAMPLE_TYPE& msType, const unsigned int& quality )
  {
    switch( msType )
    {
    case D3DMULTISAMPLE_NONE:
      {
        return( 1 );
      }
    case D3DMULTISAMPLE_NONMASKABLE:
      {
        return( quality + 1 );
      }
    case D3DMULTISAMPLE_2_SAMPLES:
    case D3DMULTISAMPLE_4_SAMPLES:
#if !defined(XENON) && !defined(PS3) && !defined(CAFE)
    case D3DMULTISAMPLE_3_SAMPLES:
    case D3DMULTISAMPLE_5_SAMPLES:
    case D3DMULTISAMPLE_6_SAMPLES:
    case D3DMULTISAMPLE_7_SAMPLES:
    case D3DMULTISAMPLE_8_SAMPLES:
    case D3DMULTISAMPLE_9_SAMPLES:
    case D3DMULTISAMPLE_10_SAMPLES:
    case D3DMULTISAMPLE_11_SAMPLES:
    case D3DMULTISAMPLE_12_SAMPLES:
    case D3DMULTISAMPLE_13_SAMPLES:
    case D3DMULTISAMPLE_14_SAMPLES:
    case D3DMULTISAMPLE_15_SAMPLES:
    case D3DMULTISAMPLE_16_SAMPLES:
#endif
      {
        return( msType );
      }
    default:
      {
        assert( !"Unknown or unsupported D3DMULTISAMPLE_TYPE!" );
        return( 0 );
      }
    }
  }


void CD3D9Renderer::DisplaySplash()
{
#ifdef WIN32
  if (IsEditorMode())
    return;

  HBITMAP hImage = (HBITMAP)LoadImage(GetModuleHandle(0), "splash.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);

  if (hImage != INVALID_HANDLE_VALUE)
  {
    RECT rect;
    HDC hDC = GetDC(m_hWnd);
    HDC hDCBitmap = CreateCompatibleDC(hDC);
    BITMAP bm;

    GetClientRect(m_hWnd, &rect);
    GetObject(hImage, sizeof(bm), &bm);
    SelectObject(hDCBitmap, hImage);

    DWORD x = rect.left + (((rect.right-rect.left)-bm.bmWidth) >> 1);
    DWORD y = rect.top + (((rect.bottom-rect.top)-bm.bmHeight) >> 1);


//    BitBlt(hDC, x, y, bm.bmWidth, bm.bmHeight, hDCBitmap, 0, 0, SRCCOPY);

		RECT Rect;
		GetWindowRect( m_hWnd, &Rect );
		StretchBlt( hDC, 0, 0, Rect.right - Rect.left, Rect.bottom - Rect.top,  hDCBitmap, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY );

    DeleteObject(hImage);
    DeleteDC(hDCBitmap);
  }
#endif
}

//=====================================================================================

bool CD3D9Renderer::SetCurrentContext(WIN_HWND hWnd)
{
  uint32 i;

  for (i=0; i<m_RContexts.Num(); i++)
  {
    if (m_RContexts[i]->m_hWnd == hWnd)
      break;
  }
  if (i == m_RContexts.Num())
    return false;

  if (m_CurrContext == m_RContexts[i])
    return true;

  m_CurrContext = m_RContexts[i];

  CHWShader::m_pCurVS = NULL;
  CHWShader::m_pCurPS = NULL;

  return true;
}

bool CD3D9Renderer::CreateContext(WIN_HWND hWnd, bool bAllowMSAA)
{
  uint32 i;

  for (i=0; i<m_RContexts.Num(); i++)
  {
    if (m_RContexts[i]->m_hWnd == hWnd)
      break;
  }
  if (i != m_RContexts.Num())
    return true;
  SD3DContext *pContext = new SD3DContext;
  pContext->m_hWnd = (HWND)hWnd;
  pContext->m_X = 0;
  pContext->m_Y = 0;
  pContext->m_Width = m_width;
  pContext->m_Height = m_height;
#if defined(DIRECT3D10)
  pContext->m_pSwapChain = 0;
  pContext->m_pBackBuffer = 0;
#endif
	pContext->m_nViewportWidth = m_width;
	pContext->m_nViewportHeight = m_height;
	pContext->m_nSSSamplesX = 1;
	pContext->m_nSSSamplesY = 1;
	pContext->m_bMainViewport = false;
  m_CurrContext = pContext;
  m_RContexts.AddElem(pContext);

  return true;
}

bool CD3D9Renderer::DeleteContext(WIN_HWND hWnd)
{
  uint32 i, j;

  for (i=0; i<m_RContexts.Num(); i++)
  {
    if (m_RContexts[i]->m_hWnd == hWnd)
      break;
  }
  if (i == m_RContexts.Num())
    return false;
  if (m_CurrContext == m_RContexts[i])
  {
    for (j=0; j<m_RContexts.Num(); j++)
    {
      if (m_RContexts[j]->m_hWnd != hWnd)
      {
        m_CurrContext = m_RContexts[j];
        break;
      }
    }
    if (j == m_RContexts.Num())
      m_CurrContext = NULL;
  }
#if defined(DIRECT3D10)
  SAFE_RELEASE(m_RContexts[i]->m_pSwapChain);
  SAFE_RELEASE(m_RContexts[i]->m_pBackBuffer);
#endif
  delete m_RContexts[i];
  m_RContexts.Remove(i, 1);

  return true;
}

void CD3D9Renderer::MakeMainContextActive()
{
  if (m_RContexts.empty() || m_CurrContext == m_RContexts[0])
    return;

  m_CurrContext = m_RContexts[0];

  CHWShader::m_pCurVS = NULL;
  CHWShader::m_pCurPS = NULL;
}

bool CD3D9Renderer::CreateMSAADepthBuffer()
{
  HRESULT hr = S_OK;
#if defined (DIRECT3D9)
  if (CV_r_msaa)
  {
    if (m_RP.m_MSAAData.Type != (D3DMULTISAMPLE_TYPE)CV_r_msaa_samples || m_RP.m_MSAAData.Quality != CV_r_msaa_quality || !m_RP.m_MSAAData.m_pZBuffer)
    {
      m_RP.m_MSAAData.Type = (D3DMULTISAMPLE_TYPE)CV_r_msaa_samples;
      m_RP.m_MSAAData.Quality = CV_r_msaa_quality;
      SAFE_RELEASE(m_RP.m_MSAAData.m_pZBuffer);
      hr = m_pd3dDevice->CreateDepthStencilSurface(m_width, m_height, D3DFMT_D24S8, m_RP.m_MSAAData.Type, m_RP.m_MSAAData.Quality, FALSE, &m_RP.m_MSAAData.m_pZBuffer, NULL);
      assert(hr == S_OK);
      m_DepthBufferOrigMSAA.pSurf = m_RP.m_MSAAData.m_pZBuffer;
    }
  }
  else
  {
    m_RP.m_MSAAData.Type = D3DMULTISAMPLE_NONE;
    m_RP.m_MSAAData.Quality = 0;

    SAFE_RELEASE(m_RP.m_MSAAData.m_pZBuffer);
    m_DepthBufferOrigMSAA.pSurf = m_pZBuffer;
  }
#elif defined (DIRECT3D10)
  if (CV_r_msaa)
  {
    if (m_RP.m_MSAAData.Type != CV_r_msaa_samples || m_RP.m_MSAAData.Quality != CV_r_msaa_quality)
    {
      SAFE_RELEASE(m_RP.m_MSAAData.m_pZBuffer);
      SAFE_RELEASE(m_RP.m_MSAAData.m_pDepthTex);
    }
    m_RP.m_MSAAData.Type = CV_r_msaa_samples;
    m_RP.m_MSAAData.Quality = CV_r_msaa_quality;
    if (m_RP.m_MSAAData.Type > 1 && !m_RP.m_MSAAData.m_pZBuffer)
    {
      // Create depth stencil texture
      ID3D11Texture2D* pDepthStencil = NULL;
      D3D11_TEXTURE2D_DESC descDepth;
			ZeroStruct(descDepth);
      descDepth.Width = m_width;
      descDepth.Height = m_height;
      descDepth.MipLevels = 1;
      descDepth.ArraySize = 1;
      descDepth.Format = m_ZFormat;
      descDepth.SampleDesc.Count = m_RP.m_MSAAData.Type;
      descDepth.SampleDesc.Quality = m_RP.m_MSAAData.Quality;
      descDepth.Usage = D3D11_USAGE_DEFAULT;
      descDepth.BindFlags = D3D11_BIND_DEPTH_STENCIL;
      descDepth.CPUAccessFlags = 0;
      descDepth.MiscFlags = 0;
      hr = m_pd3dDevice->CreateTexture2D( &descDepth, NULL, &m_RP.m_MSAAData.m_pDepthTex);
      if (FAILED(hr))
        return false;
      m_DepthBufferOrigMSAA.pTex = m_RP.m_MSAAData.m_pDepthTex;

      // Create the depth stencil view
      D3D11_DEPTH_STENCIL_VIEW_DESC descDSV;
			ZeroStruct(descDSV);
      descDSV.Format = descDepth.Format;
      descDSV.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS;
      hr = m_pd3dDevice->CreateDepthStencilView(m_RP.m_MSAAData.m_pDepthTex, &descDSV, &m_RP.m_MSAAData.m_pZBuffer);
      if (FAILED(hr))
        return false;
      m_DepthBufferOrigMSAA.pSurf = m_RP.m_MSAAData.m_pZBuffer;
    }
  }
  else
  {
    m_RP.m_MSAAData.Type = 0;
    m_RP.m_MSAAData.Quality = 0;

    SAFE_RELEASE(m_RP.m_MSAAData.m_pZBuffer);
    SAFE_RELEASE(m_RP.m_MSAAData.m_pDepthTex);
    m_DepthBufferOrigMSAA.pSurf = m_pZBuffer;
  }
#endif
  return (hr == S_OK);
}

bool CD3D9Renderer::ChangeResolution(int nNewWidth, int nNewHeight, int nNewColDepth, int nNewRefreshHZ, bool bFullScreen, bool bForceReset)
{
  if (m_bDeviceLost)
    return true;

#if defined(WIN32) || defined(WIN64)
	if (m_pRT && CV_r_multithreaded == 1 && m_pRT->IsRenderThread())
	{
		assert(0);
		return false;
	}
	ForceFlushRTCommands();
#endif

#if !defined(XENON)
  iLog->Log("Change resolution: %dx%dx%d (%s)", nNewWidth, nNewHeight, nNewColDepth, bFullScreen ? "Fullscreen" : "Windowed");

  m_bInResolutionChange = false;
  int nPrevWidth = CRenderer::m_width;
  int nPrevHeight = CRenderer::m_height;
  int nPrevColorDepth = CRenderer::m_cbpp;
  bool bPrevFullScreen = m_bFullScreen;
  if (nNewWidth < 320)
    nNewWidth = 320;
  if (nNewHeight < 240)
    nNewHeight = 240;
  if (nNewColDepth < 24)
    nNewColDepth = 16;
  else
    nNewColDepth = 32;
  bool bNeedReset = bForceReset || (nNewColDepth != nPrevColorDepth || bPrevFullScreen != bFullScreen || nNewHeight != nPrevHeight || nNewWidth != nPrevWidth);

  // Save the new dimensions
  m_width  = nNewWidth;
  m_height = nNewHeight;
  m_cbpp   = nNewColDepth;
  m_bFullScreen = bFullScreen;
  if (!IsEditorMode())
    m_VSync = CV_r_vsync;
  else
    m_VSync = 0;
  if (bFullScreen && nNewColDepth == 16)
  {
    m_zbpp = 16;
    m_sbpp = 0;
  }

  DeleteContext(m_hWnd);

 #if defined(USE_DXUT)
  DXUTDeviceSettings *pDevSettings = DXUTGetCurrentDeviceSettings();
 #endif

  RestoreGamma();
  
	bool bFullscreenWindow = false;
#if defined(WIN32) || defined(WIN64)
	bFullscreenWindow = CV_r_FullscreenWindow && CV_r_FullscreenWindow->GetIVal() != 0;
#endif

  if (IsEditorMode() && !bForceReset)
  {
    nNewWidth = m_deskwidth;
    nNewHeight = m_deskheight;
  }
  HRESULT hr = S_OK;
  if (bNeedReset)
  {
 #if !defined(PS3) && !defined(gringo) && !defined(CAFE)
		pDevSettings->d3d9.pp.BackBufferWidth = nNewWidth;
    pDevSettings->d3d9.pp.BackBufferHeight = nNewHeight;
 #endif
 #if defined (DIRECT3D9)
		hr = DXUTCreateDevice(!m_bFullScreen, nNewWidth, nNewHeight, m_sbpp, m_cbpp);
		OnD3D9PostCreateDevice(DXUTGetD3D9Device());
 #elif defined(DIRECT3D10) && defined(USE_DXUT)
		//hr = DXUTCreateDevice(D3D_FEATURE_LEVEL_11_0, !m_bFullScreen, nNewWidth, nNewHeight);
    //DXUTResizeDXGIBuffers(m_width, m_height, bFullScreen);
    //DXUTDeviceSettings deviceSettings = DXUTGetDeviceSettings();
    //deviceSettings.d3d11.sd.Windowed = !bFullScreen;
    //deviceSettings.d3d11.sd.BufferDesc.Width = nNewWidth;
    //deviceSettings.d3d11.sd.BufferDesc.Height = nNewHeight;
    //DXUTResizeDXGIBuffers(m_width, m_height, bFullScreen);
    DXUTDeviceSettings* pDeviceSettings = DXUTGetCurrentDeviceSettings();
    DXUTDeviceSettings deviceSettings = *pDeviceSettings;
    deviceSettings.d3d11.sd.Windowed = !bFullScreen;
    deviceSettings.d3d11.sd.BufferDesc.Width = nNewWidth;
    deviceSettings.d3d11.sd.BufferDesc.Height = nNewHeight;
    DXUTSnapDeviceSettingsToEnumDevice(&deviceSettings, false);
    m_width = nNewWidth = pDeviceSettings->d3d11.sd.BufferDesc.Width = deviceSettings.d3d11.sd.BufferDesc.Width;
    m_height = nNewHeight = pDeviceSettings->d3d11.sd.BufferDesc.Height = deviceSettings.d3d11.sd.BufferDesc.Height;
    pDeviceSettings->d3d11.sd.Windowed = !bFullScreen;
    pDeviceSettings->d3d11.SyncInterval = CV_r_vsync ? 1 : 0;

    ID3D11DepthStencilView* pDSV = NULL;
    ID3D11RenderTargetView* pRTVs[8] = {0};
    m_pd3dDeviceContext->OMSetRenderTargets( 8, pRTVs, pDSV );
    m_DepthBufferOrig.Release();
    m_DepthBufferOrigMSAA.Release();

		if (!IsEditorMode())
		{
			if (!m_bFullScreen && !bFullscreenWindow)
			{
				const int x = m_prefMonX + (m_prefMonWidth - m_width) / 2;
				const int y = m_prefMonY + (m_prefMonHeight - m_height) / 2;
				const int wdt = GetSystemMetrics(SM_CXDLGFRAME) * 2 + m_width;
				const int hgt = GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CXDLGFRAME)*2 + m_height;
				SetWindowLong(m_hWnd, GWL_STYLE, m_dwWindowStyle);
				SetWindowPos(m_hWnd, HWND_NOTOPMOST, x, y, wdt, hgt, SWP_SHOWWINDOW);
			}
			else if(bFullscreenWindow)
			{
				const int x = m_prefMonX + (m_prefMonWidth - m_width) / 2;
				const int y = m_prefMonY + (m_prefMonHeight - m_height) / 2;
				SetWindowLong(m_hWnd, GWL_STYLE, WS_POPUP|WS_VISIBLE);
				SetWindowPos(m_hWnd, HWND_NOTOPMOST, x, y, m_width, m_height, SWP_SHOWWINDOW);
			}
			else
			{
				const int x = m_prefMonX;
				const int y = m_prefMonY;
				SetWindowLong(m_hWnd, GWL_STYLE, WS_POPUP|WS_VISIBLE);
				SetWindowPos(m_hWnd, HWND_NOTOPMOST, x, y, m_width, m_height, SWP_SHOWWINDOW);
			}
		}

    m_pSwapChain->SetFullscreenState(bFullScreen, NULL);
    m_pSwapChain->ResizeTarget(&pDeviceSettings->d3d11.sd.BufferDesc);
    DXUTResizeDXGIBuffers(m_width, m_height, bFullScreen);
    //DXUTCheckForWindowChangingMonitors();
		OnD3D10PostCreateDevice(DXUTGetD3D11Device());
		if(gEnv->pHardwareMouse)
			gEnv->pHardwareMouse->GetSystemEventListener()->OnSystemEvent(ESYSTEM_EVENT_TOGGLE_FULLSCREEN, bFullScreen ? 1 : 0, 0);
 #endif
    nNewWidth = m_width;
    nNewHeight = m_height;
#if defined(WIN32) || defined(WIN64)
    m_pRT->RC_SetViewport(0, 0, nNewWidth, nNewHeight);
#else
    RT_SetViewport(0, 0, nNewWidth, nNewHeight);
#endif
    m_MainViewport.nX = 0;
    m_MainViewport.nY = 0;
    m_MainViewport.nWidth = nNewWidth;
    m_MainViewport.nHeight = nNewHeight;
		m_MainRTViewport.nX = 0;
		m_MainRTViewport.nY = 0;
		m_MainRTViewport.nWidth = nNewWidth;
		m_MainRTViewport.nHeight = nNewHeight;
  }

  AdjustWindowForChange();

 #ifdef WIN32
  if (!bFullScreen && !bFullscreenWindow && !IsEditorMode())
  {
		const int x = m_prefMonX + (m_prefMonWidth - CRenderer::m_width) / 2;
		const int y = m_prefMonY + (m_prefMonHeight - CRenderer::m_height) / 2;
		const int wdt = GetSystemMetrics(SM_CXDLGFRAME) * 2 + CRenderer::m_width;
		const int hgt = GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CXDLGFRAME)*2 + CRenderer::m_height;
		SetWindowPos(m_hWnd, HWND_NOTOPMOST, x, y, wdt, hgt, SWP_SHOWWINDOW);
  }
	else if(bFullscreenWindow && !IsEditorMode())
	{
		const int x = m_prefMonX + (m_prefMonWidth - CRenderer::m_width) / 2;
		const int y = m_prefMonY + (m_prefMonHeight - CRenderer::m_height) / 2;
		SetWindowPos(m_hWnd, HWND_NOTOPMOST, x, y, m_width, m_height, SWP_SHOWWINDOW);
	}
  else
  if (m_bFullScreen)
  {
		SetWindowText(m_hWnd, m_WinTitle);

    iLog->Log("Final resolution: %dx%dx%d (%s)", m_width, m_height, nNewColDepth, bFullScreen ? "Fullscreen" : "Windowed");
  }
 #endif //WIN32

  CreateMSAADepthBuffer();

  CreateContext(m_hWnd, CV_r_msaa != 0);

 #if defined (DIRECT3D9)
  hr = m_pd3dDevice->BeginScene();
 #endif

  ICryFont *pCryFont = gEnv->pCryFont;
  if (pCryFont)
  {
    IFFont *pFont = pCryFont->GetFont("default");
  }
  if (m_CVWidth)
  m_CVWidth->Set(CRenderer::m_width);
  if (m_CVHeight)
  m_CVHeight->Set(CRenderer::m_height);
  /*if (m_CVFullScreen)
  m_CVFullScreen->Set(m_bFullScreen);
  if (m_CVColorBits)
  m_CVColorBits->Set(CRenderer::m_cbpp);
  ChangeViewport(0, 0, CRenderer::m_width, CRenderer::m_height);*/

  PostDeviceReset();
















































































#endif

  m_bInResolutionChange = false;

  return true;
}

void CD3D9Renderer::PostDeviceReset()
{
  m_bDeviceLost = 0;
  if (m_bFullScreen)
    SetGamma(CV_r_gamma+m_fDeltaGamma, CV_r_brightness, CV_r_contrast, true);
  FX_ResetPipe();
  CHWShader::m_pCurVS = NULL;
  CHWShader::m_pCurPS = NULL;

#if defined (DIRECT3D9)
  for (int i=0; i<224; i++)
  {
    CHWShader_D3D::m_CurPSParams[i] = Vec4(0,0,0,0);
  }
  for (int i=0; i<256; i++)
  {
    CHWShader_D3D::m_CurVSParams[i] = Vec4(0,0,0,0);
  }
#endif

  for (int i=0; i<MAX_TMU; i++)
  {
    CTexture::s_TexStages[i].m_Texture = NULL;
  }
  m_nFrameReset++;
}


//-----------------------------------------------------------------------------
// Name: CD3D9Renderer::AdjustWindowForChange()
// Desc: Prepare the window for a possible change between windowed mode and
//       fullscreen mode.  This function is virtual and thus can be overridden
//       to provide different behavior, such as switching to an entirely
//       different window for fullscreen mode (as in the MFC sample apps).
//-----------------------------------------------------------------------------
HRESULT CD3D9Renderer::AdjustWindowForChange()
{
#if defined(USE_DXUT)
  if (IsEditorMode())
    return S_OK;

	bool bFullscreenWindow = false;
#if defined(WIN32) || defined(WIN64)
	bFullscreenWindow = CV_r_FullscreenWindow && CV_r_FullscreenWindow->GetIVal() != 0;
#endif

	if( !m_bFullScreen && !bFullscreenWindow)
  {
    // Set windowed-mode style
    SetWindowLong( m_hWnd, GWL_STYLE, m_dwWindowStyle );
  }
  else
  {
    // Set fullscreen-mode style
    SetWindowLong( m_hWnd, GWL_STYLE, WS_POPUP|WS_VISIBLE );
  }
  DXUTDeviceSettings* pDev = DXUTGetCurrentDeviceSettings();
#if defined (DIRECT3D9)
  if (m_width != m_pd3dpp->BackBufferWidth || m_height != m_pd3dpp->BackBufferHeight)
  {
    m_width = m_pd3dpp->BackBufferWidth;
    m_height = m_pd3dpp->BackBufferHeight;
    _SetVar("r_Width", m_width);
    _SetVar("r_Height", m_height);

    int x, y, wdt, hgt;
    if (m_bFullScreen || bFullscreenWindow)
    {
      x = 0;
      y = 0;
      wdt = m_width;
      hgt = m_height;
      SetWindowPos(m_hWnd, bFullscreenWindow ? HWND_NOTOPMOST : HWND_TOPMOST, x, y, wdt, hgt, SWP_SHOWWINDOW);
    }
    else if (gEnv->pSystem->IsBrowserMode())
    {
      x = (GetSystemMetrics(SM_CXFULLSCREEN)-m_width)/2;
      y = (GetSystemMetrics(SM_CYFULLSCREEN)-m_height)/2;
      wdt = m_width;
      hgt = m_height;
      SetWindowPos(m_hWnd, HWND_NOTOPMOST, x, y, wdt, hgt, SWP_SHOWWINDOW);
    }
    else
    {
      x = (GetSystemMetrics(SM_CXFULLSCREEN)-m_width)/2;
      y = (GetSystemMetrics(SM_CYFULLSCREEN)-m_height)/2;
      wdt = GetSystemMetrics(SM_CXDLGFRAME)*2 + m_width;
      hgt = GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CXDLGFRAME)*2 + m_height;
      SetWindowPos(m_hWnd, HWND_NOTOPMOST, x, y, wdt, hgt, SWP_SHOWWINDOW);
    }

    RT_SetViewport(0, 0, m_width, m_height);
    m_MainViewport.nX = 0;
    m_MainViewport.nY = 0;
    m_MainViewport.nWidth = m_width;
    m_MainViewport.nHeight = m_height;
		m_MainRTViewport.nX = 0;
		m_MainRTViewport.nY = 0;
		m_MainRTViewport.nWidth = m_width;
		m_MainRTViewport.nHeight = m_height;

  }
#elif defined (DIRECT3D10)
  {
    _SetVar("r_Width", m_width);
    _SetVar("r_Height", m_height);
    if (m_bFullScreen)
    {
			const int x = m_prefMonX;
			const int y = m_prefMonY;
			const int wdt = m_width;
			const int hgt = m_height;
			SetWindowPos(m_hWnd, HWND_TOPMOST, x, y, wdt, hgt, SWP_SHOWWINDOW);
    }
    else if (bFullscreenWindow)
    {
			const int x = m_prefMonX + (m_prefMonWidth - m_width) / 2;
			const int y = m_prefMonY + (m_prefMonHeight - m_height) / 2;
			const int wdt = m_width;
			const int hgt = m_height;
			SetWindowPos(m_hWnd, HWND_NOTOPMOST, x, y, wdt, hgt, SWP_SHOWWINDOW);
		}
    else
    {
			const int x = m_prefMonX + (m_prefMonWidth - m_width) / 2;
			const int y = m_prefMonY + (m_prefMonHeight - m_height) / 2;
			const int wdt = GetSystemMetrics(SM_CXDLGFRAME) * 2 + m_width;
			const int hgt = GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CXDLGFRAME) * 2 + m_height;
			SetWindowPos(m_hWnd, HWND_NOTOPMOST, x, y, wdt, hgt, SWP_SHOWWINDOW);
    }

		//set viewport to ensure we have a valid one, even when doing chainloading
		// and playing a video before going ingame
		m_MainViewport.nX = 0;
		m_MainViewport.nY = 0;
		m_MainViewport.nWidth = m_width;
		m_MainViewport.nHeight = m_height;
		m_MainRTViewport.nX = 0;
		m_MainRTViewport.nY = 0;
		m_MainRTViewport.nWidth = m_width;
		m_MainRTViewport.nHeight = m_height;
#if defined(WIN32) || defined(WIN64)
		m_pRT->RC_SetViewport(0, 0, m_width, m_height);
#else
    RT_SetViewport(0, 0, m_width, m_height);
#endif
  }
#endif
#endif // defined(USE_DXUT)

  return S_OK;
}

static inline bool SortDispFormat(const SDispFormat& a, const SDispFormat& b)
{
	if (a.m_Width != b.m_Width)
		return a.m_Width < b.m_Width;
	if (a.m_Height != b.m_Height)
		return a.m_Height < b.m_Height;
	return a.m_BPP < b.m_BPP;
};

int CD3D9Renderer::EnumDisplayFormats(SDispFormat* formats)
{
	int numFormats = 0;

#if defined(USE_DXUT)

	std::vector<SDispFormat> tmpModeList;

#if defined (DIRECT3D9)
  DXUTDeviceSettings* pDev = DXUTGetCurrentDeviceSettings();
  CD3D9Enumeration* pd3dEnum = DXUTGetD3D9Enumeration();
  CD3D9EnumAdapterInfo* pAdapterInfo = pd3dEnum->GetAdapterInfo(pDev->d3d9.AdapterOrdinal);

	tmpModeList.reserve(pAdapterInfo->displayModeList.GetSize());
	for (int i=0; i<pAdapterInfo->displayModeList.GetSize(); ++i)
	{
		D3DDISPLAYMODE* pDM = &pAdapterInfo->displayModeList.GetAt(i);
		if (pDM->Width >= 640 && pDM->Height >= 480)
		{
			unsigned int bpp = CTexture::BitsPerPixel(CTexture::TexFormatFromDeviceFormat(pDM->Format));
			if (bpp <= 32)
			{
				SDispFormat df;
				df.m_Width = pDM->Width;
				df.m_Height = pDM->Height;
				df.m_BPP = (bpp == 24) ? 32 : bpp;
				tmpModeList.push_back(df);
			}
		}
	}
#elif defined(DIRECT3D10)
	DXUTDeviceSettings* pDev = DXUTGetCurrentDeviceSettings();
	CD3D11Enumeration* pd3dEnum = DXUTGetD3D11Enumeration();
	CD3D11EnumAdapterInfo* pAdapterInfo = pd3dEnum->GetAdapterInfo(pDev->d3d11.AdapterOrdinal);

	if (pAdapterInfo->outputInfoList.GetSize() > 0)
	{
		CD3D11EnumOutputInfo* pModes(pAdapterInfo->outputInfoList.GetAt(0));		
		tmpModeList.reserve(pModes->displayModeList.GetSize());
		for (int i=0; i<pModes->displayModeList.GetSize(); ++i)
		{
			DXGI_MODE_DESC* pDM = &pModes->displayModeList.GetAt(i);
			if (pDM->Width >= 640 && pDM->Height >= 480)
			{
				unsigned int bpp = CTexture::BitsPerPixel(CTexture::TexFormatFromDeviceFormat(pDM->Format));
				if (bpp <= 32)
				{
					SDispFormat df;
					df.m_Width = pDM->Width;
					df.m_Height = pDM->Height;
					df.m_BPP = (bpp == 24) ? 32 : bpp;
					tmpModeList.push_back(df);
				}
			}
		}
	}
#endif

	if (!tmpModeList.empty())
	{
		std::sort(tmpModeList.begin(), tmpModeList.end(), SortDispFormat);

		int prevWidth = 0, prevHeight = 0, prevBpp = 0;
		for (uint32 i=0; i<tmpModeList.size(); ++i)
		{
			const SDispFormat& df = tmpModeList[i];
			if (df.m_Width != prevWidth || df.m_Height != prevHeight || df.m_BPP != prevBpp)
			{
				if (formats)
					formats[numFormats] = df;

				prevWidth = df.m_Width;
				prevHeight = df.m_Height;
				prevBpp = df.m_BPP;

				++numFormats;
			}
		}
	}

#endif // defined(USE_DXUT)

	return numFormats;
}

bool CD3D9Renderer::ChangeDisplay(unsigned int width,unsigned int height,unsigned int cbpp)
{
  return false;
}


void CD3D9Renderer::UnSetRes()
{
  m_Features |= RFT_SUPPORTZBIAS;

#ifdef _DEBUG
	m_d3dDebug.Release();
#endif

#if defined(USE_DXUT)
  DXUTShutdown();
#endif
}

void CD3D9Renderer::DestroyWindow(void)  
{
#ifdef WIN32
  if (m_hWnd)
  {
    ::DestroyWindow(m_hWnd);
    m_hWnd = NULL;
  }
#endif
}

#if defined(WIN32) || defined(XENON)

	static CD3D9Renderer::gammaramp_t orgGamma;

	#ifndef XENON
		static BOOL doGamma = false;
	#endif

#endif

void CD3D9Renderer::RestoreGamma(void)
{
	//if (!m_bFullScreen)
	//	return;

	if (!(GetFeatures() & RFT_HWGAMMA))
    return;

  if (CV_r_nohwgamma)
    return;

  m_fLastGamma = 1.0f;
  m_fLastBrightness = 0.5f;
  m_fLastContrast = 0.5f;

  //iLog->Log("...RestoreGamma");

#if defined(WIN32) || defined(WIN64)
  if ( !doGamma )
	  return;

  doGamma = false;

	m_hWndDesktop = GetDesktopWindow();

	if( HDC dc = GetDC(m_hWndDesktop) )
	{
		SetDeviceGammaRamp(dc, &orgGamma);
		ReleaseDC(m_hWndDesktop, dc);
	}




#endif
}

void CD3D9Renderer::GetDeviceGamma()
{
#if defined(WIN32) || defined(WIN64)
	if( doGamma )
	{
		return;
	}

	m_hWndDesktop = GetDesktopWindow();

	if( HDC dc = GetDC(m_hWndDesktop) )
	{
		doGamma = true;
		
		if( !GetDeviceGammaRamp(dc, &orgGamma) )
		{
			for(uint16 i = 0; i < 256; i++)
			{
				orgGamma.red  [i] = i * 0x101;
				orgGamma.green[i] = i * 0x101;
				orgGamma.blue [i] = i * 0x101;
			}
		}

		ReleaseDC(m_hWndDesktop, dc);
	}





#endif
}

void CD3D9Renderer::SetDeviceGamma(gammaramp_t* gamma)  
{
  if (!(GetFeatures() & RFT_HWGAMMA))
    return;

  if (CV_r_nohwgamma)
    return;

#if defined(WIN32) || defined(WIN64)
  if ( !doGamma )
	  return;

  m_hWndDesktop = GetDesktopWindow();  // TODO: DesktopWindow - does not represent actual output window thus gamma affects all desktop monitors !!!

  if( HDC dc = GetDC(m_hWndDesktop) )
  {
	  doGamma = true;
	  // INFO!!! - very strange: in the same time
	  // GetDeviceGammaRamp -> TRUE
	  // SetDeviceGammaRamp -> FALSE but WORKS!!!
	  // at least for desktop window DC... be careful
	  SetDeviceGammaRamp(dc, gamma); 
	  ReleaseDC(m_hWndDesktop, dc);
  }





#endif
}

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
// Utilies for xenon to remove tv gamma

float GammaFunc_2_2( float f ) { return powf( f, 1.0f / 2.2f ); }
float DegammaFunc_2_2( float f ) { return powf( f, 2.2f ); }

float DegammaFuncTV( float f )
{
	if( f <= 0.0812f )
	{
		return f / 4.5f;
	}
	else
	{
		return powf( ( f + 0.099f ) / 1.099f, 1.0f / 0.45f );
	}
}

float GammaFuncSRGB( float f )
{
	if( f <= 0.0031308f )
	{
		return f * 12.92f;
	}
	else
	{
		return powf( f, 1.0f / 2.4f ) * 1.055f - 0.055f;
	}
}

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

void CD3D9Renderer::SetGamma(float fGamma, float fBrightness, float fContrast, bool bForce)
{
	if (m_pStereoRenderer)  // Function can be called on shutdown
		fGamma += GetS3DRend().GetGammaAdjustment();

	fGamma = CLAMP(fGamma, 0.4f, 1.6f);







  if (!bForce && m_fLastGamma == fGamma && m_fLastBrightness == fBrightness && m_fLastContrast == fContrast)
    return;

  GetDeviceGamma();

  gammaramp_t gamma;

	float fInvGamma = 1.f / fGamma;

	float fAdd = (fBrightness-0.5f)*0.5f - fContrast*0.5f + 0.25f;
	float fMul = fContrast+0.5f;

	for (int i=0; i<256; i++)
	{
		float pfInput[3];

#if defined(WIN32) || defined(XENON)
		pfInput[0] = (float)(orgGamma.red  [i] >> 8) / 255.f;
		pfInput[1] = (float)(orgGamma.green[i] >> 8) / 255.f;
		pfInput[2] = (float)(orgGamma.blue [i] >> 8) / 255.f;
#else
		pfInput[0] = (float)i / 255.f;
		pfInput[1] = pfInput[0];
		pfInput[2] = pfInput[0];
#endif
		pfInput[0] = cry_powf(pfInput[0], fInvGamma) * fMul + fAdd;
		pfInput[1] = cry_powf(pfInput[1], fInvGamma) * fMul + fAdd;
		pfInput[2] = cry_powf(pfInput[2], fInvGamma) * fMul + fAdd;
		 
























		gamma.red  [i] = CLAMP(int_round(pfInput[0] * 65535.f), 0, 65535);
		gamma.green[i] = CLAMP(int_round(pfInput[1] * 65535.f), 0, 65535);
		gamma.blue [i] = CLAMP(int_round(pfInput[2] * 65535.f), 0, 65535);
	}

  //iLog->Log("...SetGamma %.3f", fGamma);
  SetDeviceGamma(&gamma);


  m_fLastGamma = fGamma;
  m_fLastBrightness = fBrightness;
  m_fLastContrast = fContrast;
}

bool CD3D9Renderer::SetGammaDelta(const float fGamma)
{
  m_fDeltaGamma = fGamma;
  SetGamma(CV_r_gamma + fGamma, CV_r_brightness, CV_r_contrast, false);
  return true;
}

SD3DSurface::~SD3DSurface()
{
#if defined(DIRECT3D9)
	Release();
#endif
}

void SD3DSurface::Release(bool bReleaseTex)
{
#if defined (DIRECT3D10)
	ID3D11DepthStencilView* pDSV = (ID3D11DepthStencilView* )pSurf;
	SAFE_RELEASE(pDSV);
	if (bReleaseTex && pTex)
	{
			((ID3D11Texture2D*)(pTex))->Release();
	}
#elif defined (DIRECT3D9)
  LPDIRECT3DSURFACE9 pSrf = (LPDIRECT3DSURFACE9)(pSurf);
  SAFE_RELEASE(pSrf);
#endif
  pSurf = NULL;
}


void CD3D9Renderer::ShutDownFast()
{




#ifndef XENON
  // Flush RT command buffer
  ForceFlushRTCommands();
  CHWShader::mfFlushPendedShadersWait(-1);
#ifndef _RELEASE
  m_cEF.mfFlushFullPLCombinations();
#endif
  FX_PipelineShutdown();
  //CBaseResource::ShutDown();
  memset(&CTexture::s_TexStages[0], 0, sizeof(CTexture::s_TexStages));
  for (uint32 i=0; i<CTexture::s_TexStates.size(); i++)
  {
    memset(&CTexture::s_TexStates[i], 0, sizeof(STexState));
  }
  SAFE_DELETE(m_pRT);

	m_DynIB.Release();
	for (uint32 i=0; i<POOL_MAX; i++)
		m_DynVB[i].Release();

#endif

}

void CD3D9Renderer::RT_ShutDown(uint32 nFlags)
{
  CREBreakableGlassBuffer::RT_ReleaseInstance();
  delete(&LPVManager);
  SAFE_DELETE(m_pColorGradingControllerD3D);
  SAFE_DELETE(m_pPostProcessMgr);
  SAFE_DELETE(m_pWaterSimMgr);
  SAFE_DELETE(m_pStereoRenderer);
	SAFE_DELETE(m_pPipelineProfiler);
  CHWShader::mfFlushPendedShadersWait(-1);
  if (nFlags == FRR_ALL)
  {
    memset(&CTexture::s_TexStages[0], 0, sizeof(CTexture::s_TexStages));
    CTexture::s_TexStates.clear();
    FreeResources(FRR_ALL);
  }

  FX_PipelineShutdown();

#if defined(USE_DXUT)
  DXUTShutdown();
#endif

#if defined(DIRECT3D10) && !defined(PS3)
  SAFE_RELEASE(m_pd3dDeviceContext);
#endif




#ifndef EXCLUDE_SCALEFORM_SDK
  SF_DestroyResources();
#endif
#if defined(ENABLE_RENDER_AUX_GEOM)
  SAFE_DELETE(m_pRenderAuxGeomD3D);
#endif
  m_DepthBufferOrig.pSurf = NULL;
  m_DepthBufferOrigMSAA.pSurf = NULL;

#if defined (DIRECT3D9)
  assert(!m_pCaptureFrameSurf[0]);
  for (int i=0; i<sizeof(m_pCaptureFrameSurf) / sizeof(m_pCaptureFrameSurf[0]); ++i)
    SAFE_RELEASE(m_pCaptureFrameSurf[i]);
#endif
}

void CD3D9Renderer::ShutDown(bool bReInit)
{
  m_bInShutdown = true;

  // Force Flush RT command buffer
  ForceFlushRTCommands();
  PreShutDown();
#ifndef _RELEASE
  m_cEF.mfFlushFullPLCombinations();
#endif
  m_pRT->RC_ShutDown(bReInit ? (FRR_SHADERS | FRR_TEXTURES | FRR_REINITHW) : FRR_ALL);

  //CBaseResource::ShutDown();
  ForceFlushRTCommands();




  //////////////////////////////////////////////////////////////////////////
  // Clear globals.
  //////////////////////////////////////////////////////////////////////////

  STLALLOCATOR_CLEANUP
	for (uint32 id=0;id<RT_COMMAND_BUF_COUNT;++id)
	{
		delete m_RP.m_TI[id].m_matView;
		delete m_RP.m_TI[id].m_matProj;
	}

  SAFE_DELETE(m_pRT);

	if(!bReInit)
	{
		m_DynIB.Release();
		for (uint32 i=0; i<POOL_MAX; i++)
			m_DynVB[i].Release();
	}

  if (!bReInit)
  {
    iLog = NULL;
    //iConsole = NULL;
    iTimer = NULL;
    iSystem = NULL;
  }

	PostShutDown();
}

#ifdef WIN32
LRESULT CALLBACK LowLevelKeyboardProc (INT nCode, WPARAM wParam, LPARAM lParam)
{
	KBDLLHOOKSTRUCT *pkbhs = (KBDLLHOOKSTRUCT *) lParam;
	BOOL bControlKeyDown = 0;    
	switch (nCode)
	{
	case HC_ACTION:
		{
			if (pkbhs->vkCode == VK_TAB && pkbhs->flags & LLKHF_ALTDOWN)
				return 1;            // Disable ALT+ESC
		}       
	default:
		break;
	}
	return CallNextHookEx (0, nCode, wParam, lParam);
} 
#endif

bool CD3D9Renderer::SetWindow(int width, int height, bool fullscreen, WIN_HWND hWnd)
{
#ifdef WIN32
  DWORD style, exstyle;
  int x, y, wdt, hgt;
  
  if (width < 640)
    width = 640;
  if (height < 480)
    height = 480;

	if (gEnv->pSystem->IsBrowserMode())
		m_dwWindowStyle = WS_CHILD | WS_VISIBLE;
	else
		m_dwWindowStyle = WS_OVERLAPPEDWINDOW | WS_VISIBLE;

	// Do not allow the user to resize the window
	m_dwWindowStyle &= ~WS_MAXIMIZEBOX;
	m_dwWindowStyle &= ~WS_THICKFRAME;

	bool bFullscreenWindow = false;
#if defined(WIN32) || defined(WIN64)
	bFullscreenWindow = CV_r_FullscreenWindow && CV_r_FullscreenWindow->GetIVal() != 0;
#endif

  if (fullscreen || bFullscreenWindow)
  {
		exstyle = bFullscreenWindow ? WS_EX_APPWINDOW : WS_EX_TOPMOST;
		style = WS_POPUP | WS_VISIBLE;
		x = m_prefMonX + (m_prefMonWidth - width) / 2;
		y = m_prefMonY + (m_prefMonHeight - height) / 2;
		wdt = width;
		hgt = height;
  }
  else if (gEnv->pSystem->IsBrowserMode())
  {
    exstyle = 0;
    style = m_dwWindowStyle;
		x = m_prefMonX + (m_prefMonWidth - width) / 2;
		y = m_prefMonY + (m_prefMonHeight - height) / 2;
    wdt = width;
    hgt = height;
  }
  else
  {
		exstyle = WS_EX_APPWINDOW;
		style = m_dwWindowStyle;
		x = m_prefMonX + (m_prefMonWidth - width) / 2;
		y = m_prefMonY + (m_prefMonHeight - height) / 2;
		wdt = GetSystemMetrics(SM_CXFIXEDFRAME) * 2 + width;
		hgt = GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYFIXEDFRAME) * 2 + height;
  }

  if (IsEditorMode())
  {
    m_dwWindowStyle = WS_OVERLAPPED;
    style = m_dwWindowStyle;
    exstyle = 0;
    x = y = 0;
    wdt = 100;
    hgt = 100;

    WNDCLASS wc;
    memset(&wc, 0, sizeof(WNDCLASS));
    wc.style         = CS_OWNDC;
    wc.lpfnWndProc   = DefWindowProc;
    wc.hInstance     = m_hInst;
//    wc.hbrBackground =(HBRUSH)GetStockObject(BLACK_BRUSH);
    wc.lpszMenuName  = 0;
    wc.lpszClassName = "D3DDeviceWindowClassForSandbox";
    if (!RegisterClass(&wc))
    {
      CryFatalError( "Cannot Register Window Class %s",wc.lpszClassName );
      return false;
    }
    m_hWnd = CreateWindowEx(exstyle, wc.lpszClassName, m_WinTitle, style, x, y, wdt, hgt, NULL,NULL, m_hInst, NULL);
    ShowWindow( m_hWnd, SW_HIDE );
  }
  else
  {
    if (!hWnd)
    {
      m_hWnd = CreateWindowEx(exstyle,"CryENGINE",m_WinTitle,style,x,y,wdt,hgt, NULL, NULL, m_hInst, NULL);

      // Create second window for stereo (multi-head device)
			
      if( GetS3DRend().GetStereoDevice() == STEREO_DEVICE_DUALHEAD && fullscreen )
      {
        m_hWnd2 = CreateWindowEx(exstyle,"CryENGINE",m_WinTitle,style,x,y,wdt,hgt, m_hWnd, NULL, m_hInst, NULL);
      }
      else
      {
        m_hWnd2 = 0;
      }
	  if ( fullscreen && (!gEnv->pSystem->IsDevMode() && CV_r_enableAltTab == 0) )
		 SetWindowsHookEx(WH_KEYBOARD_LL,LowLevelKeyboardProc,NULL,0);
    }
    else
      m_hWnd = (HWND)hWnd;
    ShowWindow(m_hWnd, SW_SHOWNORMAL);
    SetFocus(m_hWnd);
    SetForegroundWindow(m_hWnd);
  }

  if (!m_hWnd)
    iConsole->Exit("Couldn't create window\n");

#endif //WIN32
  return true;
}

#if defined (DIRECT3D9) && !defined (XENON)

void CD3D9Renderer::SuccessfullyLaunchFromMediaCenter() const
{
	if (m_hWnd && IsWindow(m_hWnd))
	{
		typedef IDirect3D9* (WINAPI *FP_Direct3DCreate9)(UINT);
		FP_Direct3DCreate9 pd3dc9((FP_Direct3DCreate9) GetProcAddress(LoadLibrary("d3d9.dll"), "Direct3DCreate9"));		
		IDirect3D9* pD3D(pd3dc9 ? pd3dc9(D3D_SDK_VERSION) : 0);
		if (pD3D)
		{
			D3DPRESENT_PARAMETERS presentParams;
			memset(&presentParams, 0, sizeof(presentParams));
			presentParams.BackBufferWidth = 640;
			presentParams.BackBufferHeight = 480;
			presentParams.BackBufferFormat = D3DFMT_A8R8G8B8;
			presentParams.BackBufferCount = 1;
			presentParams.MultiSampleType = D3DMULTISAMPLE_NONE;
			presentParams.MultiSampleQuality = 0;
			presentParams.SwapEffect = D3DSWAPEFFECT_DISCARD;
			presentParams.hDeviceWindow = m_hWnd;
			presentParams.Windowed = TRUE;
			presentParams.EnableAutoDepthStencil = TRUE;
			presentParams.AutoDepthStencilFormat = D3DFMT_D24S8;
			presentParams.Flags = 0;
			presentParams.FullScreen_RefreshRateInHz = 0;
			presentParams.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;

			CTimeValue startTime(gEnv->pTimer->GetAsyncTime());
			while (true)
			{
				MSG msg;
				// Must be PeekMessageW for Scaleform IME to function correctly and to ensure WM_CHAR contains
				// Unicode widechar for languages like Russian
				while (PeekMessageW(&msg, m_hWnd, 0, 0, PM_REMOVE))       
				{
					TranslateMessage(&msg);
					DispatchMessage(&msg);
				}

				Sleep(50);

				IDirect3DDevice9* pDev(0);
				if (SUCCEEDED(pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, m_hWnd, 
					D3DCREATE_PUREDEVICE | D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE, &presentParams, &pDev)))
				{
					SAFE_RELEASE(pDev);
					break;
				}

				CTimeValue curTime(gEnv->pTimer->GetAsyncTime());
				if ((curTime - startTime).GetSeconds() > 5.0f)
				{
					Warning("It's taken more than five seconds to create a Direct3D9 device after launching"
						" from Media Center. Successful render initialization cannot be guaranteed!");
					break;
				}
			}

			SAFE_RELEASE(pD3D);
		}
	}
}
#endif

#define QUALITY_VAR(name) \
  static void OnQShaderChange_Shader##name( ICVar *pVar )\
{\
  int iQuality = eSQ_Low;\
  if(gRenDev->GetFeatures() & (RFT_HW_SM2X | RFT_HW_SM30))\
  iQuality = CLAMP(pVar->GetIVal(), 0, eSQ_Max);\
  gRenDev->EF_SetShaderQuality(eST_##name,(EShaderQuality)iQuality);\
}

QUALITY_VAR(General)
QUALITY_VAR(Metal)
QUALITY_VAR(Glass)
QUALITY_VAR(Vegetation)
QUALITY_VAR(Ice)
QUALITY_VAR(Terrain)
QUALITY_VAR(Shadow)
QUALITY_VAR(Water)
QUALITY_VAR(FX)
QUALITY_VAR(PostProcess)
QUALITY_VAR(HDR)
QUALITY_VAR(Sky)

#undef QUALITY_VAR

static void OnQShaderChange_Renderer( ICVar *pVar )
{
  int iQuality = eRQ_Low;

  if(gRenDev->GetFeatures() & (RFT_HW_SM2X | RFT_HW_SM30))
    iQuality = CLAMP(pVar->GetIVal(), 0, eSQ_Max);
  else
    pVar->ForceSet("0");

  gRenDev->m_RP.m_eQuality = (ERenderQuality)iQuality;
}


static void Command_Quality(IConsoleCmdArgs* Cmd)
{
  bool bLog=false;
  bool bSet=false;

  int iQuality = -1;

  if(Cmd->GetArgCount()==2)
  {
    iQuality = CLAMP(atoi(Cmd->GetArg(1)), 0, eSQ_Max);
    bSet=true;
  }
  else bLog=true;

  if(bLog)iLog->LogWithType(IMiniLog::eInputResponse," ");
  if(bLog)iLog->LogWithType(IMiniLog::eInputResponse,"Current quality settings (0=low/1=med/2=high/3=very high):");

#define QUALITY_VAR(name) if(bLog)iLog->LogWithType(IMiniLog::eInputResponse,"  $3q_"#name" = $6%d",gEnv->pConsole->GetCVar("q_"#name)->GetIVal()); \
  if(bSet)gEnv->pConsole->GetCVar("q_"#name)->Set(iQuality);

  QUALITY_VAR(ShaderGeneral)
    QUALITY_VAR(ShaderMetal)
    QUALITY_VAR(ShaderGlass)
    QUALITY_VAR(ShaderVegetation)
    QUALITY_VAR(ShaderIce)
    QUALITY_VAR(ShaderTerrain)
    QUALITY_VAR(ShaderShadow)
    QUALITY_VAR(ShaderWater)
    QUALITY_VAR(ShaderFX)
    QUALITY_VAR(ShaderPostProcess)
    QUALITY_VAR(ShaderHDR)
    QUALITY_VAR(ShaderSky)
    QUALITY_VAR(Renderer)

#undef QUALITY_VAR

    if(bSet)iLog->LogWithType(IMiniLog::eInputResponse,"Set quality to %d",iQuality);
}

const char *sGetSQuality(const char *szName)
{
  ICVar *pVar = iConsole->GetCVar(szName);
  assert(pVar);
  if (!pVar)
    return "Unknown";
  int iQ = pVar->GetIVal();
  switch (iQ)
  {
    case eSQ_Low:
      return "Low";
    case eSQ_Medium:
      return "Medium";
    case eSQ_High:
      return "High";
    case eSQ_VeryHigh:
      return "VeryHigh";
    default:
      return "Unknown";
  }
}

static void Command_ColorGradingChartImage(IConsoleCmdArgs* pCmd)
{
	CColorGradingControllerD3D* pCtrl = gcpRendD3D->m_pColorGradingControllerD3D;
	if (pCmd && pCtrl)
	{
		const int numArgs = pCmd->GetArgCount();
		if (numArgs == 1)
		{
			const CTexture* pChart = pCtrl->GetStaticColorChart();
			if (pChart)
				iLog->Log("current static chart is \"%s\"", pChart->GetName());
			else
				iLog->Log("no static chart loaded");
		}
		else if (numArgs == 2)
		{
			const char* pArg = pCmd->GetArg(1);
			if (pArg && pArg[0])
			{
				if (pArg[0] == '0' && !pArg[1])
				{
					pCtrl->LoadStaticColorChart(0);
					iLog->Log("static chart reset");
				}
				else
				{
					if (pCtrl->LoadStaticColorChart(pArg))
						iLog->Log("\"%s\" loaded successfully", pArg);
					else
						iLog->Log("failed to load \"%s\"", pArg);
				}
			}
		}
	}
}

















WIN_HWND CD3D9Renderer::Init(int x,int y,int width,int height,unsigned int cbpp, int zbpp, int sbits, bool fullscreen,WIN_HINSTANCE hinst, WIN_HWND Glhwnd, bool bReInit, const SCustomRenderInitArgs* pCustomArgs, bool bShaderCacheGen)
{
  LOADING_TIME_PROFILE_SECTION(GetISystem());

  MEMSTAT_CONTEXT(EMemStatContextTypes::MSC_Other, 0, "Renderer initialisation");

  if (!iSystem || !iLog)
    return 0;

  iLog->Log("Initializing Direct3D and creating game window:");
  INDENT_LOG_DURING_SCOPE();

  bool b = false;
  m_CVWidth = iConsole->GetCVar("r_Width");
  m_CVHeight = iConsole->GetCVar("r_Height");
  m_CVFullScreen = iConsole->GetCVar("r_Fullscreen");
  m_CVDisplayInfo = iConsole->GetCVar("r_DisplayInfo");
  m_CVColorBits = iConsole->GetCVar("r_ColorBits");

#if defined(WIN32) || defined(WIN64)
	CV_r_FullscreenWindow = iConsole->GetCVar("r_FullscreenWindow");
	m_fullscreenWindow = CV_r_FullscreenWindow && CV_r_FullscreenWindow->GetIVal();
	{
		RECT rcDesk;
		GetWindowRect(GetDesktopWindow(), &rcDesk);

		m_prefMonX = rcDesk.left;
		m_prefMonY = rcDesk.top;
		m_prefMonWidth = rcDesk.right - rcDesk.left;
		m_prefMonHeight = rcDesk.bottom - rcDesk.top;
	}
	{
		RECT rc;
		HDC hdc = GetDC(NULL);
		GetClipBox(hdc, &rc);
		ReleaseDC(NULL, hdc);
		m_deskwidth = rc.right  - rc.left;
		m_deskheight = rc.bottom - rc.top;
	}
#endif

#ifdef D3DX_SDK_VERSION
	iLog->Log( "D3DX_SDK_VERSION = %d", D3DX_SDK_VERSION );
#else
	iLog->Log( "D3DX_SDK_VERSION = <UNDEFINED>" );
#endif

#if defined (DIRECT3D9)
  iLog->Log ("Direct3D9 driver is creating...");
  iLog->Log ("Crytek Direct3D9 driver version %4.2f (%s <%s>)", VERSION_D3D, __DATE__, __TIME__);
#elif defined (DIRECT3D10)
  iLog->Log ("Direct3D11 driver is creating...");
  iLog->Log ("Crytek Direct3D11 driver version %4.2f (%s <%s>)", VERSION_D3D, __DATE__, __TIME__);
#endif

  const char * sGameName = iConsole->GetCVar("cvGameName")->GetString();








  strncpy (m_WinTitle, sGameName, sizeof(m_WinTitle));


  if (iConsole->GetCVar("cvDoVerboseWindowTitle")->GetIVal())
  {
	  snprintf(m_WinTitle, sizeof(m_WinTitle), "- %s" WINDOWNAME_GFXVERSION " - " __DATE__ " (" __TIME__ ")", sGameName);
  }

  // Both snprintf and strncpy can leave this buffer non NULL-terminated if tried to write too much into it, so...
  m_WinTitle[sizeof(m_WinTitle) - 1] = '\0';
  iLog->Log ("Creating window called '%s' (%dx%d)", m_WinTitle, width, height);

  m_hInst = (HINSTANCE)hinst;

  if (Glhwnd == (WIN_HWND)1)
  {
    Glhwnd = 0;
    m_bEditor = true;
    fullscreen = false;
  }

	m_bShaderCacheGen = bShaderCacheGen;

  // Save the new dimensions
  m_width  = width;
  m_height = height;
  m_cbpp   = cbpp;
  m_zbpp   = zbpp; 
  m_sbpp   = sbits;
  m_bFullScreen = fullscreen;

	// only create device if we are not in shader cache generation mode
	if (!m_bShaderCacheGen)
	{
		// call init stereo before device is created!
		m_pStereoRenderer->InitDeviceBeforeD3D();

		while (true)
		{
			m_hWnd = (HWND)Glhwnd;

			// Creates Device here.
			bool bRes = m_pRT->RC_CreateDevice();
			if (!bRes)
			{
				ShutDown(true);
				return 0;
			}

#if defined (DIRECT3D9) && !defined (XENON)
			if (pCustomArgs && pCustomArgs->appStartedFromMediaCenter)
				SuccessfullyLaunchFromMediaCenter();
#endif

			break;
		}

#if defined (DIRECT3D9)
#if !defined(XENON) && !defined(PS3) && !defined(CAFE)
		DXUTDeviceSettings* pDev = DXUTGetCurrentDeviceSettings();
		CD3D9Enumeration* pd3dEnum = DXUTGetD3D9Enumeration();
		CD3D9EnumAdapterInfo* pAdapterInfo = pd3dEnum->GetAdapterInfo(pDev->d3d9.AdapterOrdinal);
		D3DADAPTER_IDENTIFIER9 *ai = NULL;
		D3DADAPTER_IDENTIFIER9 adapter_info;
		if (pAdapterInfo)
			ai = &pAdapterInfo->AdapterIdentifier;
		else
		{
			ai = &adapter_info;
			memset(ai,0,sizeof(adapter_info));
			strcpy( ai->Description,"NULL REF" );
			strcpy( ai->DeviceName,"NULL REF" );
			strcpy( ai->Driver,"NULL REF" );
		}
		iLog->Log(" ****** D3D9 CryRender Stats ******");
		iLog->Log(" Driver description: %s", ai->Description);
		iLog->Log(" Full stats: %s", m_strDeviceStats);
		iLog->Log(" Hardware acceleration: %s", (pDev->d3d9.DeviceType == D3DDEVTYPE_HAL) ? "Yes" : "No");
#endif

		if (CV_r_msaa)
		{
			TArray<SAAFormat> Formats;

			int nNum = GetAAFormat(Formats, false);
			iLog->Log(" Full scene AA: Enabled: %s (%d Quality)", Formats[nNum].szDescr, Formats[nNum].nQuality);
			GetAAFormat(Formats, true);
		}
		else
			iLog->Log(" Full scene AA: Disabled");
		iLog->Log(" Current Resolution: %dx%dx%d %s", CRenderer::m_width, CRenderer::m_height, CRenderer::m_cbpp, m_bFullScreen ? "Full Screen" : "Windowed");
		iLog->Log(" Maximum texture size: %dx%d (Max Aspect: %d)", m_pd3dCaps->MaxTextureWidth, m_pd3dCaps->MaxTextureHeight, m_pd3dCaps->MaxTextureAspectRatio);
		iLog->Log(" Default textures filtering type: %s", CV_d3d9_texturefilter->GetString());
		iLog->Log(" HDR Rendering: %s", m_nHDRType == 1 ? "FP16" : m_nHDRType == 2 ? "MRT" : "Disabled");
		iLog->Log(" MRT HDR Rendering: %s", (m_bDeviceSupportsFP16Separate) ? "Enabled" : "Disabled");
		iLog->Log(" Occlusion queries: %s", (m_Features & RFT_OCCLUSIONTEST) ? "Supported" : "Not supported");
		iLog->Log(" Geometry instancing: %s", (m_bDeviceSupportsInstancing) ? "Supported" : "Not supported");
		iLog->Log(" Vertex textures: %s", (m_bDeviceSupportsVertexTexture) ? "Supported" : "Not supported");  
		iLog->Log(" Render to vertex buffer: %s", (m_bDeviceSupportsR2VB) ? "Supported" : "Not supported");  
		iLog->Log(" R16F rendertarget: %s", (m_bDeviceSupportsR16FRendertarget) ? "Supported" : "Not supported");
		iLog->Log(" NormalMaps compression : %s", m_Format3Dc.IsValid() ? "Supported" : "Not supported");
		iLog->Log(" Gamma control: %s", (m_Features & RFT_HWGAMMA) ? "Hardware" : "Software");
		iLog->Log(" Vertex Shaders version %d.%d", D3DSHADER_VERSION_MAJOR(m_pd3dCaps->VertexShaderVersion), D3DSHADER_VERSION_MINOR(m_pd3dCaps->VertexShaderVersion));
		iLog->Log(" Pixel Shaders version %d.%d", D3DSHADER_VERSION_MAJOR(m_pd3dCaps->PixelShaderVersion), D3DSHADER_VERSION_MINOR(m_pd3dCaps->PixelShaderVersion));
#elif defined (DIRECT3D10)

#if defined(USE_DXUT)
		DXUTDeviceSettings* pDev = DXUTGetCurrentDeviceSettings();
		CD3D11Enumeration* pd3dEnum = DXUTGetD3D11Enumeration();
		CD3D11EnumDeviceInfo* pd3dEnumInfo = pd3dEnum->GetDeviceInfo(pDev->d3d11.AdapterOrdinal, pDev->d3d11.DriverType);
		CD3D11EnumAdapterInfo* pAdapterInfo = pd3dEnum->GetAdapterInfo(pDev->d3d11.AdapterOrdinal);

		iLog->Log(" ****** D3D11 CryRender Stats ******");
#  ifndef __SNC__
		iLog->Log(" Driver description: %S", pAdapterInfo->szUniqueDescription);
#endif
		switch(pd3dEnumInfo->MaxLevel)
		{
		case D3D_FEATURE_LEVEL_9_1: iLog->Log(" Feature level: DirectX 9.1"); break;
		case D3D_FEATURE_LEVEL_9_2: iLog->Log(" Feature level: DirectX 9.2"); break;
		case D3D_FEATURE_LEVEL_9_3: iLog->Log(" Feature level: DirectX 9.3"); break;
		case D3D_FEATURE_LEVEL_10_0: iLog->Log(" Feature level: DirectX 10.0"); break;
		case D3D_FEATURE_LEVEL_10_1: iLog->Log(" Feature level: DirectX 10.1"); break;
		case D3D_FEATURE_LEVEL_11_0: iLog->Log(" Feature level: DirectX 11.0"); break;
		}
		iLog->Log(" Full stats: %s", m_strDeviceStats);
		if (pDev->d3d11.DriverType == D3D_DRIVER_TYPE_HARDWARE)
			iLog->Log(" Rasterizer: Hardware");
		else
			if (pDev->d3d11.DriverType == D3D_DRIVER_TYPE_REFERENCE)
				iLog->Log(" Rasterizer: Reference");
			else
				if (pDev->d3d11.DriverType == D3D_DRIVER_TYPE_SOFTWARE)
					iLog->Log(" Rasterizer: Software");

		//iLog->Log(" Full screen only: %s", (di->d3dCaps.Caps2 & D3DCAPS2_CANRENDERWINDOWED) ? "No" : "Yes");
		if (CV_r_msaa)
		{
			TArray<SAAFormat> Formats;

			int nNum = GetAAFormat(Formats, false);
			iLog->Log(" Full scene AA: Enabled: %s (%d Quality)", Formats[nNum].szDescr, Formats[nNum].nQuality);
			GetAAFormat(Formats, true);
		}
		else
			iLog->Log(" Full scene AA: Disabled");
#endif //defined(USE_DXUT)
		iLog->Log(" Current Resolution: %dx%dx%d %s", CRenderer::m_width, CRenderer::m_height, CRenderer::m_cbpp, m_bFullScreen ? "Full Screen" : "Windowed");
		iLog->Log(" Texture filtering type: %s", CV_d3d9_texturefilter->GetString());
		iLog->Log(" HDR Rendering: %s", m_nHDRType == 1 ? "FP16" : m_nHDRType == 2 ? "MRT" : "Disabled");
		iLog->Log(" MRT HDR Rendering: %s", (m_bDeviceSupportsFP16Separate) ? "Enabled" : "Disabled");
		iLog->Log(" Occlusion queries: %s", (m_Features & RFT_OCCLUSIONTEST) ? "Supported" : "Not supported");
		iLog->Log(" Geometry instancing: %s", (m_bDeviceSupportsInstancing) ? "Supported" : "Not supported");
		iLog->Log(" Vertex textures: %s", (m_bDeviceSupportsVertexTexture) ? "Supported" : "Not supported");
		iLog->Log(" Render to vertex buffer: %s", (m_bDeviceSupportsR2VB) ? "Supported" : "Not supported");  
		iLog->Log(" R16F rendertarget: %s", (m_bDeviceSupportsR16FRendertarget) ? "Supported" : "Not supported");
		iLog->Log(" NormalMaps compression : %s", m_Format3Dc.IsValid() ? "Supported" : "Not supported");
		iLog->Log(" Gamma control: %s", (m_Features & RFT_HWGAMMA) ? "Hardware" : "Software");




		iLog->Log(" Vertex Shaders version %d.%d", 4, 0);
		iLog->Log(" Pixel Shaders version %d.%d", 4, 0);

#endif

		CRenderer::ChangeGeomInstancingThreshold();		// to get log printout and to set the internal value (vendor dependent)

#if defined (DIRECT3D9)
		if (D3DSHADER_VERSION_MAJOR(m_pd3dCaps->PixelShaderVersion) >= 3)
		{
			m_Features |= RFT_HW_SM20 | RFT_HW_SM2X | RFT_HW_SM30;
		}
		else
			if (D3DSHADER_VERSION_MAJOR(m_pd3dCaps->PixelShaderVersion) >= 2)
			{
				m_Features |= RFT_HW_SM20;
				if (D3DSHADER_VERSION_MINOR(m_pd3dCaps->PixelShaderVersion) > 0 || m_pd3dCaps->PS20Caps.NumInstructionSlots >= 256)
				{
					m_Features |= RFT_HW_SM2X;
				}
			}
#elif defined (DIRECT3D10)
		m_Features |= RFT_HW_SM20 | RFT_HW_SM2X | RFT_HW_SM30;
#endif

#ifndef USE_HDR
		m_Features &= ~RFT_HW_HDR;
#endif

#if !defined(XENON) && !defined(PS3)
		if (!m_bDeviceSupportsInstancing)
			_SetVar("r_GeomInstancing", 0);
#endif

		const char *str = NULL;
#if defined (DIRECT3D9)
		if (m_Features & RFT_HW_SM30)
			str = "SM.3.0, SM.2.X, SM.2.0 and SM.1.1";
		else
			if (m_Features & RFT_HW_SM2X)
				str = "SM.2.x, SM.2.0 and SM.1.1";
			else
				if (m_Features & RFT_HW_SM20)
					str = "SM.2.0 and SM.1.1";
#elif defined (DIRECT3D10)




		if (m_Features & RFT_HW_SM40)
			str = "SM.4.0";
		else
			if (m_Features & RFT_HW_SM50)
				str = "SM.5.0";
			else
				assert(0);

#endif
		iLog->Log(" Shader model usage: '%s'", str);

	} else {

		// force certain features during shader cache gen mode
		m_Features |= RFT_HW_SM20 | RFT_HW_SM2X | RFT_HW_SM30;

		m_bDeviceSupportsFP16Filter = true;
	}

  iLog->Log(" *****************************************");
	iLog->Log(" ");

  iLog->Log("Init Shaders");

  m_cEF.ParseMSAAProfiles();

//  if (!(GetFeatures() & (RFT_HW_PS2X | RFT_HW_PS30)))
//    SetShaderQuality(eST_All, eSQ_Low);

  // Quality console variables --------------------------------------

#define QUALITY_VAR(name) { ICVar *pVar=iConsole->Register("q_Shader"#name,&m_cEF.m_ShaderProfiles[(int)eST_##name].m_iShaderProfileQuality,1,	\
  0, CVARHELP("Defines the shader quality of "#name"\nUsage: q_Shader"#name" 0=low/1=med/2=high/3=very high (default)"),OnQShaderChange_Shader##name);\
  OnQShaderChange_Shader##name(pVar);\
  iLog->Log(" %s shader quality: %s", #name, sGetSQuality("q_Shader"#name));}   // clamp for lowspec

  QUALITY_VAR(General);
  QUALITY_VAR(Metal);
  QUALITY_VAR(Glass);
  QUALITY_VAR(Vegetation);
  QUALITY_VAR(Ice);
  QUALITY_VAR(Terrain);
  QUALITY_VAR(Shadow);
  QUALITY_VAR(Water);
  QUALITY_VAR(FX);
  QUALITY_VAR(PostProcess);
  QUALITY_VAR(HDR);
  QUALITY_VAR(Sky);


#undef QUALITY_VAR

	ICVar *pVar = REGISTER_INT("q_Renderer",3,0,"Defines the quality of Renderer\nUsage: q_Renderer 0=low/1=med/2=high/3=very high (default)");
	
	pVar->SetOnChangeCallback(OnQShaderChange_Renderer);
  OnQShaderChange_Renderer(pVar);   // clamp for lowspec, report renderer current value
  iLog->Log("Render quality: %s", sGetSQuality("q_Renderer"));

  REGISTER_COMMAND("q_Quality",&Command_Quality,0,
    "If called with a parameter it sets the quality of all q_.. variables\n"
    "otherwise it prints their current state\n"
    "Usage: q_Quality [0=low/1=med/2=high/3=very high]");

	REGISTER_COMMAND("r_ColorGradingChartImage", &Command_ColorGradingChartImage, 0,
		"If called with a parameter it loads a color chart image. This image will overwrite\n"
		" the dynamic color chart blending result and be used during post processing instead.\n"
		"If called with no parameter it displays the name of the previously loaded chart.\n"
		"To reset a previously loaded chart call r_ColorGradingChartImage 0.\n"
		"Usage: r_ColorGradingChartImage [path of color chart image/reset]");






  
	if (!bShaderCacheGen)
		m_pRT->RC_Init();

	if (!g_shaderGeneralHeap)
		g_shaderGeneralHeap = CryGetIMemoryManager()->CreateGeneralExpandingMemoryHeap(4 * 1024 * 1024, 0, "Shader General");






  m_cEF.mfInit();
  
	if (!bShaderCacheGen)
		m_pRT->RC_PrecacheDefaultShaders();

	//PostInit();


  m_bInitialized = true;

//  Cry_memcheck();







  // Success, return the window handle
  return (m_hWnd);
}

const char *CD3D9Renderer::D3DError( HRESULT h )
{
#if defined(USE_DXUT)
  const char* strHRESULT = "Unknown";
  strHRESULT = DXGetErrorString(h);
  return strHRESULT;
#else
  return "Unknown";
#endif
}

bool CD3D9Renderer::Error(char *Msg, HRESULT h)
{
  const char *str = D3DError(h);
  iLog->Log("Error: %s (%s)", Msg, str);

  //UnSetRes();

  //if (Msg)
  //  iConsole->Exit("%s (%s)", Msg, str);
  //else
  //  iConsole->Exit("(%s)", str);

  return false;
}

//=============================================================================

static char *sD3DFMT( D3DFORMAT fmt )
{
  switch( fmt )
  {
  case D3DFMT_A8R8G8B8:
    return "D3DFMT_A8R8G8B8";
  case D3DFMT_X8R8G8B8:
    return "D3DFMT_X8R8G8B8";
  case D3DFMT_R5G6B5:
    return "D3DFMT_R5G6B5";
  case D3DFMT_X1R5G5B5:
    return "D3DFMT_X1R5G5B5";
  case D3DFMT_A1R5G5B5:
    return "D3DFMT_A1R5G5B5";
  case D3DFMT_A4R4G4B4:
    return "D3DFMT_A4R4G4B4";
  case D3DFMT_X4R4G4B4:
    return "D3DFMT_X4R4G4B4";
  case D3DFMT_A2B10G10R10:
    return "D3DFMT_A2B10G10R10";
  case D3DFMT_D24S8:
    return "D3DFMT_D24S8";
  case D3DFMT_D24X8:
    return "D3DFMT_D24X8";
  case D3DFMT_D16:
    return "D3DFMT_D16";
  case D3DFMT_D32:
    return "D3DFMT_D32";
  case D3DFMT_D24FS8:
    return "D3DFMT_D24FS8";
    // Xenon does not support these formats.
#if !defined(XENON)
  case D3DFMT_R8G8B8:
    return "D3DFMT_R8G8B8";
  case D3DFMT_R3G3B2:
    return "D3DFMT_R3G3B2";
  case D3DFMT_A8R3G3B2:
    return "D3DFMT_A8R3G3B2";
  case D3DFMT_D24X4S4:
    return "D3DFMT_D24X4S4";
  case D3DFMT_D16_LOCKABLE:
    return "D3DFMT_D16_LOCKABLE";
  case D3DFMT_D32F_LOCKABLE:
    return "D3DFMT_D32F_LOCKABLE";
  case D3DFMT_D15S1:
    return "D3DFMT_D15S1";
#endif
  default:
    return "Unknown";
  }
}

struct SMultiSample
{
#if defined (DIRECT3D9)
  D3DMULTISAMPLE_TYPE Type;
#elif defined (DIRECT3D10)
  UINT Type;
#endif
  DWORD Quality;
};

int __cdecl MS_Cmp(const void* v1, const void* v2)
{
  SMultiSample *pMS0 = (SMultiSample *)v1;
  SMultiSample *pMS1 = (SMultiSample *)v2;

  if (pMS0->Type < pMS1->Type)
    return -1;
  if (pMS0->Type > pMS1->Type)
    return 1;

  if (pMS0->Quality < pMS1->Quality)
    return -1;
  if (pMS0->Quality > pMS1->Quality)
    return 1;

  return 0;
}

int __cdecl MSAA_Cmp(const void* v1, const void* v2)
{
  SAAFormat *pMS0 = (SAAFormat *)v1;
  SAAFormat *pMS1 = (SAAFormat *)v2;
  int nD0 = isdigit((unsigned char)pMS0->szDescr[0]);
  int nD1 = isdigit((unsigned char)pMS1->szDescr[0]);
  if (nD0 < nD1)
    return -1;
  if (nD0 > nD1)
    return 1;
  nD0 = atoi(pMS0->szDescr);
  nD1 = atoi(pMS1->szDescr);
  if (nD0 < nD1)
    return -1;
  if (nD0 > nD1)
    return 1;

  return stricmp(pMS0->szDescr, pMS1->szDescr);
}

//! Return all supported by video card video AA formats
int CD3D9Renderer::EnumAAFormats(const SDispFormat &rDispFmt, SAAFormat *formats)
{
	// MSAA requires HDR mode on so we require HDR capable hardware
	// search for #LABEL_MSAA_HDR
	if(!(gRenDev->GetFeatures()&RFT_HW_HDR))
		return 0;

	// Andrey todo
	//
	// make use of rDispFmt

  TArray<SAAFormat> SupAA;

#if defined (DIRECT3D9)
 #if !defined(XENON) && !defined(PS3)
  int32 i;
  SAAFormat DF;
  CD3D9Enumeration* pd3dEnum = DXUTGetD3D9Enumeration();
  DXUTDeviceSettings* pDev = DXUTGetCurrentDeviceSettings();
  CD3D9EnumDeviceSettingsCombo* pCombo = pd3dEnum->GetDeviceSettingsCombo(&pDev->d3d9);
  CGrowableArray<D3DMULTISAMPLE_TYPE>* pMultiSampleList = &pCombo->multiSampleTypeList;
  CD3D9EnumAdapterInfo* pAdapterInfo = pd3dEnum->GetAdapterInfo(pDev->d3d9.AdapterOrdinal);

  TArray <SMultiSample> MSList;
  int nNONMaskable = 0;
  int nMaskable = 0;
  int nQuality = 0;
  for (i=0; i<pMultiSampleList->GetSize(); i++)
  {
    if (pMultiSampleList->GetAt(i) == D3DMULTISAMPLE_NONE)
      continue;
    SMultiSample MS;
    MS.Type = pMultiSampleList->GetAt(i);
    if (MS.Type == D3DMULTISAMPLE_NONMASKABLE)
      nNONMaskable++;
    else
      nMaskable++;
    int nQualities = pCombo->multiSampleQualityList[i];
    for (int j=0; j<nQualities; j++)
    {
      MS.Quality = j;
      MSList.AddElem(MS);
      if (MS.Type == D3DMULTISAMPLE_NONMASKABLE)
        nQuality++;
    }
  }
  qsort(&MSList[0], MSList.Num(), sizeof(MSList[0]), MS_Cmp);
  DF.nAPIType = D3DMULTISAMPLE_NONMASKABLE;
  DF.nQuality = 0;
  DF.nSamples = 1;
  char str[64];
  int nVendorID = pAdapterInfo->AdapterIdentifier.VendorId;
  int nDevID = pAdapterInfo->AdapterIdentifier.DeviceId;
  for (i=0; i<(int)MSList.Num(); i++)
  {
    int nMSAA;
    SMultiSample *pS = &MSList[i];
    SMSAAMode *pMode = NULL;
    for (nMSAA=0; nMSAA<m_cEF.m_MSAAModes.size(); nMSAA++)
    {
      SMSAAProfile *pMSAA = &m_cEF.m_MSAAModes[nMSAA];
      SDevID *pDev = pMSAA->pDeviceGroup;
      assert(pDev);
      if (!pDev)
        continue;
      if (pDev->nVendorID != nVendorID)
        continue;
      int nDev;
      for (nDev=0; nDev<pDev->DevMinMax.size(); nDev++)
      {
        SMinMax *pMM = &pDev->DevMinMax[nDev];
        if (pMM->nMin<=nDevID && pMM->nMax>=nDevID)
          break;
      }
      if (nDev == pDev->DevMinMax.size())
        continue;
      for (int nM=0; nM<pMSAA->Modes.size(); nM++)
      {
        SMSAAMode *pM = &pMSAA->Modes[nM];
        if (pS->Type != pM->nSamples)
          continue;
        if (pS->Quality != pM->nQuality)
          continue;
        pMode = pM;
        break;
      }
    }
    if (pMode)
    {
      DF.nAPIType = pS->Type;
      DF.nQuality = pS->Quality;
      DF.nSamples = pS->Type;
      strcpy(DF.szDescr, pMode->szDescr);
      if (formats)
        formats[SupAA.Num()] = DF;
      SupAA.AddElem(DF);
    }
  }
  for (i=0; i<(int)MSList.Num(); i++)
  {
    SMultiSample *pS = &MSList[i];
    if (pS->Quality == 0 && MSList[i].Type>=2)
    {
      sprintf(str, "%dx", pS->Type);
      int j;
      for (j=0; j<(int)SupAA.Num(); j++)
      {
        if (!stricmp(SupAA[j].szDescr, str))
          break;
      }
      if (j == SupAA.Num())
      {
        DF.nAPIType = pS->Type;
        DF.nQuality = pS->Quality;
        DF.nSamples = pS->Type;
        strcpy(DF.szDescr, str);
        if (formats)
          formats[SupAA.Num()] = DF;
        SupAA.AddElem(DF);
      }
    }
  }
 #endif
#elif defined (DIRECT3D10) && defined(USE_DXUT)
  int32 i;
  SAAFormat DF;
  CD3D11Enumeration* pd3dEnum = DXUTGetD3D11Enumeration();
  DXUTDeviceSettings* pDev = DXUTGetCurrentDeviceSettings();
  CD3D11EnumDeviceSettingsCombo* pCombo = pd3dEnum->GetDeviceSettingsCombo(&pDev->d3d11);
  CD3D11EnumDeviceInfo *pDI = pCombo->pDeviceInfo;
  CGrowableArray<UINT>* pMultiSampleList = &pCombo->multiSampleCountList;

  TArray <SMultiSample> MSList;
  int nNONMaskable = 0;
  int nMaskable = 0;
  int nQuality = 0;
  for (i=0; i<pMultiSampleList->GetSize(); i++)
  {
    if (pMultiSampleList->GetAt(i) == 0)
      continue;
    SMultiSample MS;
    MS.Type = pMultiSampleList->GetAt(i);
    nMaskable++;
    int nQualities = pCombo->multiSampleQualityList[i];
    for (int j=0; j<nQualities; j++)
    {
      MS.Quality = j;
      MSList.AddElem(MS);
    }
  }
	if(MSList.Num())
		qsort(&MSList[0], MSList.Num(), sizeof(MSList[0]), MS_Cmp);

  DF.nAPIType = 0;
  DF.nQuality = 0;
  DF.nSamples = 1;
  char str[64];

  CD3D11EnumAdapterInfo* pAdapterInfo = pd3dEnum->GetAdapterInfo(pDev->d3d11.AdapterOrdinal);
  int nVendorID = pAdapterInfo->AdapterDesc.VendorId;
  int nDevID = pAdapterInfo->AdapterDesc.DeviceId;
  for (i=0; i<(int)MSList.Num(); i++)
  {
    int nMSAA;
    SMultiSample *pS = &MSList[i];
    SMSAAMode *pMode = NULL;
    for (nMSAA=0; nMSAA<m_cEF.m_MSAAModes.size(); nMSAA++)
    {
      SMSAAProfile *pMSAA = &m_cEF.m_MSAAModes[nMSAA];
      SDevID *pDev = pMSAA->pDeviceGroup;
      assert(pDev);
      if (!pDev)
        continue;
      if (pDev->nVendorID != nVendorID)
        continue;
      int nDev;
      for (nDev=0; nDev<pDev->DevMinMax.size(); nDev++)
      {
        SMinMax *pMM = &pDev->DevMinMax[nDev];
        if (pMM->nMin<=nDevID && pMM->nMax>=nDevID)
          break;
      }
      if (nDev == pDev->DevMinMax.size())
        continue;
      for (int nM=0; nM<pMSAA->Modes.size(); nM++)
      {
        SMSAAMode *pM = &pMSAA->Modes[nM];
        if (pS->Type != pM->nSamples)
          continue;
        if (pS->Quality != pM->nQuality)
          continue;
        pMode = pM;
        break;
      }
    }
    if (pMode)
    {
      DF.nAPIType = pS->Type;
      DF.nQuality = pS->Quality;
      DF.nSamples = pS->Type;
      strcpy(DF.szDescr, pMode->szDescr);
      if (formats)
        formats[SupAA.Num()] = DF;
      SupAA.AddElem(DF);
    }
  }
  for (i=0; i<(int)MSList.Num(); i++)
  {
    SMultiSample *pS = &MSList[i];
    if (pS->Quality == 0 && MSList[i].Type>=2)
    {
      sprintf(str, "%dx", pS->Type);
      uint32 j;
      for (j=0; j<SupAA.Num(); j++)
      {
        if (!stricmp(SupAA[j].szDescr, str))
          break;
      }
      if (j == SupAA.Num())
      {
        DF.nAPIType = pS->Type;
        DF.nQuality = pS->Quality;
        DF.nSamples = pS->Type;
        strcpy(DF.szDescr, str);
        if (formats)
          formats[SupAA.Num()] = DF;
        SupAA.AddElem(DF);
      }
    }
  }
#endif

















  if (formats)
    qsort(&formats[0], SupAA.Num(), sizeof(SAAFormat), MSAA_Cmp);

  return SupAA.Num();
}

int CD3D9Renderer::GetAAFormat(TArray<SAAFormat>& Formats, bool bReset)
{
	if(bReset)
	{
		Formats.Free();
		return 0;
	}

	SDispFormat DispFmt;

	DispFmt.m_Width=GetWidth();
	DispFmt.m_Height=GetHeight();
	DispFmt.m_BPP=GetColorBpp();

	int nNums = EnumAAFormats(DispFmt,NULL);
	if (nNums > 0)
	{
		SAAFormat *formatArray = new SAAFormat[nNums];
		EnumAAFormats(DispFmt,formatArray);

		for(int aa = 0; aa < nNums; ++aa)
		{
			Formats.push_back(formatArray[aa]);
		}
		delete [] formatArray;
	}

  if (bReset)
    return nNums;
  uint32 i;

  if (!CV_r_msaa || nNums <= 0)
    return -1;
  for (i=0; i<Formats.Num(); i++)
  {
    if (CV_r_msaa == 1 && Formats[i].nAPIType == D3DMULTISAMPLE_NONMASKABLE)
      continue;
    if (CV_r_msaa_samples == Formats[i].nSamples && CV_r_msaa_quality == Formats[i].nQuality)
      return i;
  }
  _SetVar("r_MSAA_samples", Formats[0].nSamples);
  _SetVar("r_MSAA_quality", Formats[0].nQuality);

  return 0;
}

void CD3D9Renderer::CheckMSAAChange (void)
{
#ifndef CONSOLE_CONST_CVAR_MODE
  if (IsEditorMode())
  {
    if (CV_r_msaa != m_MSAA)
    {
      CV_r_msaa = m_MSAA;
      iLog->Log("MSAA in editor mode is currently not supported");
    }
    return;
  }
#endif
  bool bChanged = false;




  if (!CV_r_HDRRendering && CV_r_msaa)
  {
		iLog->Log("MSAA in non-HDR mode is currently not supported (use \"r_HDRRendering 1\" or the options menu)");
    _SetVar("r_MSAA", 0);
  }
  if (CV_r_msaa != m_MSAA || (CV_r_msaa && (m_MSAA_quality != CV_r_msaa_quality || m_MSAA_samples != CV_r_msaa_samples)))
  {
    if (CV_r_msaa && (m_bDeviceSupports_A16B16G16R16_MSAA || m_bDeviceSupports_G16R16_MSAA))
    {
			CTexture::s_eTFZ = eTF_R32F;
      //if (m_bDeviceSupports_G16R16_MSAA)
      //  CTexture::s_eTFZ = eTF_G16R16F;
      //else
      //  CTexture::s_eTFZ = eTF_A16B16G16R16F;
      TArray<SAAFormat> Formats;
      int nNum = GetAAFormat(Formats, false);
      if (nNum < 0)
      {
        iLog->Log(" Full scene AA: Not supported\n");
        _SetVar("r_MSAA", 0);
        m_MSAA = 0;
      }
      else
      {
        iLog->Log(" Full scene AA: Enabled: %s (%d Quality)", Formats[nNum].szDescr, Formats[nNum].nQuality);
        if (Formats[nNum].nQuality != m_MSAA_quality || Formats[nNum].nSamples != m_MSAA_samples)
        {
          bChanged = true;
          _SetVar("r_MSAA_quality", Formats[nNum].nQuality);
          _SetVar("r_MSAA_samples", Formats[nNum].nSamples);
        }
        else
        if (!m_MSAA)
          bChanged = true;
        GetAAFormat(Formats, true);
      }
    }
    else
    {
      CTexture::s_eTFZ = eTF_R32F;
      bChanged = true;
      iLog->Log(" Full scene AA: Disabled");
    }
    m_MSAA = CV_r_msaa;
    m_MSAA_quality = CV_r_msaa_quality;
    m_MSAA_samples = CV_r_msaa_samples;
  }
  if (bChanged)
  {
    int nCBPP = m_cbpp;
    int nWidth = m_width;
    int nHeight = m_height;
      ChangeResolution(nWidth, nHeight, nCBPP, 75, m_CVFullScreen->GetIVal()!=0, false);
#if defined (DIRECT3D9)
    m_pd3dDevice->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, CV_r_msaa != 0);
#endif
  }
}

//==========================================================================

void CD3D9Renderer::InitATIAPI()
{
#if defined(USE_NV_API)
	assert(!m_bDriverHasActiveMultiGPU);
	
	int iGPU = AtiMultiGPUAdapters();

	m_bDriverHasActiveMultiGPU = iGPU>1;

	iLog->Log("ATI: Multi GPU count = %d",iGPU); 

  if (m_bDriverHasActiveMultiGPU)
  {
    m_nGPUs = iGPU;
  }

#endif // defined(WIN32)
}

void CD3D9Renderer::InitNVAPI()
{
#if defined(USE_NV_API)
	NvAPI_Status stat = NvAPI_Initialize();
	iLog->Log("NVAPI: API init %s (%d)", stat ? "failed" : "ok" , stat);
	m_bNVLibInitialized = stat == 0;

	if (!m_bNVLibInitialized)
		return;

	assert(!m_bDriverHasActiveMultiGPU);

	NV_DISPLAY_DRIVER_VERSION version = {0};
	version.version = NV_DISPLAY_DRIVER_VERSION_VER;

	NvAPI_Status status = NvAPI_GetDisplayDriverVersion(NVAPI_DEFAULT_HANDLE, &version);
	if (status != NVAPI_OK)
		iLog->LogError("NVAPI: Unable to get driver version (%d)", status);

	// enumerate displays
	for (int i = 0; i < NVAPI_MAX_DISPLAYS; ++i)
	{
		NvDisplayHandle displayHandle;
		status = NvAPI_EnumNvidiaDisplayHandle(i, &displayHandle);
		if (status != NVAPI_OK)
			break;
	}

	m_nGPUs = 1;

	// check SLI state to get number of GPUs available for rendering
	NV_GET_CURRENT_SLI_STATE sliState;
	sliState.version = NV_GET_CURRENT_SLI_STATE_VER;
	status = NvAPI_D3D_GetCurrentSLIState(m_pd3dDevice, &sliState);
	if (status != NVAPI_OK)
	{
		iLog->LogError("NVAPI: Unable to get SLI state (%d)", status);
	}
	else
	{
		m_nGPUs = sliState.numAFRGroups;
		if (m_nGPUs < 2)
		{
			iLog->Log("NVAPI: Single GPU system");
		}
		else
		{
			m_nGPUs = min((int)m_nGPUs, 31);
			iLog->Log("NVAPI: System configured as SLI: %d GPU(s) for rendering", m_nGPUs);
		}
	}

	m_bDriverHasActiveMultiGPU = m_nGPUs > 1;

#if defined (DIRECT3D10)
	m_bDeviceSupports_NVDBT = 1;
	iLog->Log("NVDBT supported");
#endif

#endif // defined(WIN32)
}

bool CD3D9Renderer::SetRes(void)  
{
  HRESULT hr;

  ChangeLog();
  
  m_pixelAspectRatio = 1.0f;
	m_dwCreateFlags = 0;

///////////////////////////////////////////////////////////////////






























































































































































































































































































































































































#if defined(USE_DXUT)

  UnSetRes();

#if defined (DIRECT3D9)
  DXUTSetCallbackD3D9DeviceAcceptable(IsD3D9DeviceAcceptable);
  DXUTSetCallbackD3D9DeviceCreated(OnD3D9CreateDevice);
  DXUTSetCallbackD3D9DeviceReset(OnD3D9ResetDevice);
  DXUTSetCallbackD3D9FrameRender(OnD3D9FrameRender);
  DXUTSetCallbackD3D9DeviceLost(OnD3D9LostDevice);
  DXUTSetCallbackD3D9DeviceDestroyed(OnD3D9DestroyDevice);
  DXUTSetCallbackDeviceChanging(OnD3D9DeviceChanging);
#elif defined (DIRECT3D10)
  DXUTSetCallbackD3D11DeviceAcceptable(IsD3D11DeviceAcceptable);
  DXUTSetCallbackD3D11DeviceCreated(OnD3D11CreateDevice);
  DXUTSetCallbackD3D11SwapChainResized(OnD3D11ResizedSwapChain);
  DXUTSetCallbackD3D11FrameRender(OnD3D11FrameRender);
  DXUTSetCallbackD3D11SwapChainReleasing(OnD3D11ReleasingSwapChain);
  DXUTSetCallbackD3D11DeviceDestroyed(OnD3D11DestroyDevice );
  DXUTSetCallbackDeviceChanging(OnD3D11DeviceChanging);
#endif

	WCHAR *sExtDXCmds = NULL;
	if (CD3D9Renderer::CV_d3d9_null_ref_device != 0)
	{
		sExtDXCmds = L"-forcenullref";
	}
  DXUTInit(true, true, sExtDXCmds ); // Parse the command line, show msgboxes on error, no extra command line params

	DXUTSetWindow(m_hWnd, m_hWnd, m_hWnd, m_hWnd2, false);

  int width = m_width;
  int height = m_height;
  if (IsEditorMode())
  {
    width = m_deskwidth;
    height = m_deskheight;
  }

  // DirectX9 and DirectX10 device creating
#if defined (DIRECT3D9)
	hr = DXUTCreateDevice(!m_bFullScreen, width, height, m_sbpp, m_cbpp);
#elif defined (DIRECT3D10)
  hr = DXUTCreateDevice(D3D_FEATURE_LEVEL_11_0, !m_bFullScreen, width, height);

  if (FAILED(hr))
  {
    m_Features |= RFT_HW_SM40;
    hr = DXUTCreateDevice(D3D_FEATURE_LEVEL_10_0, !m_bFullScreen, width, height);
  }
  else
    m_Features |= RFT_HW_SM50;
#endif
	if (FAILED(hr))
    return false;

	m_DevMan.AssignDevice(m_pd3dDevice);

  DXUTDeviceSettings* pDev = DXUTGetCurrentDeviceSettings();
#if defined (DIRECT3D9)
  OnD3D9PostCreateDevice(DXUTGetD3D9Device());
#elif defined (DIRECT3D10)
  //DXUTCheckForWindowSizeChange();
  //DXUTCheckForWindowChangingMonitors();
  OnD3D10PostCreateDevice(DXUTGetD3D11Device());
#endif

  AdjustWindowForChange();

  CreateContext(m_hWnd);

#else

#pragma message("Unsupported device creation function for this platform.")	

#endif	
	
  
	for(uint32 id=0;id<RT_COMMAND_BUF_COUNT;++id)
	{
		m_RP.m_TI[id].m_matView = new CMatrixStack(16, 0);
		if(m_RP.m_TI[id].m_matView == NULL)
			return false;
		m_RP.m_TI[id].m_matProj = new CMatrixStack(16, 0);
		if (m_RP.m_TI[id].m_matProj == NULL)
			return false;
	}

	m_DevMan.AssignDevice(m_pd3dDevice);
	m_pStereoRenderer->InitDeviceAfterD3D();

	return true;
} 



bool SPixFormat::CheckSupport(D3DFormat Format, const char *szDescr, ETexture_Usage eTxUsage)
{
  bool bRes = true;
  CD3D9Renderer *rd = gcpRendD3D;
#if defined (DIRECT3D10)
  D3DDevice *pDevice = rd->m_pd3dDevice;

  UINT nOptions;
  HRESULT hr = pDevice->CheckFormatSupport(Format, &nOptions);
  if (SUCCEEDED(hr))
  {
    if (nOptions & (D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_TEXTURECUBE))
    {
      bool canAutoGenMips = (nOptions & D3D11_FORMAT_SUPPORT_MIP_AUTOGEN) != 0;
			bool canReadSRGB = Format == DXGI_FORMAT_R8G8B8A8_UNORM || Format == DXGI_FORMAT_BC1_UNORM || Format == DXGI_FORMAT_BC2_UNORM || Format == DXGI_FORMAT_BC3_UNORM;
			rd->RecognizePixelFormat(*this, Format, CTexture::BitsPerPixel(CTexture::TexFormatFromDeviceFormat(Format)), szDescr, canAutoGenMips, canReadSRGB);
    }
    else
      bRes = false;
  }
  else
    bRes = false;
#else
  IDirect3D9* pD3D = rd->m_pD3D;
#if !defined(XENON) && !defined(PS3)
  DXUTDeviceSettings* pDev = DXUTGetCurrentDeviceSettings();
  D3DDEVTYPE DevType = pDev->d3d9.DeviceType;
  UINT nAdapter = pDev->d3d9.AdapterOrdinal;
  D3DFORMAT AdapterFormat = pDev->d3d9.AdapterFormat;

#endif
	DWORD usage = 0;
	switch (eTxUsage)
	{
	case (eTXUSAGE_AUTOGENMIPMAP):
		usage = D3DUSAGE_AUTOGENMIPMAP;
		break;
	case (eTXUSAGE_DEPTHSTENCIL):
		usage = D3DUSAGE_DEPTHSTENCIL;
		break;
	case (eTXUSAGE_RENDERTARGET):
		usage = D3DUSAGE_RENDERTARGET;
		break;
	default:
		break;
	}

	HRESULT hr = pD3D->CheckDeviceFormat(nAdapter, DevType, AdapterFormat, usage, D3DRTYPE_TEXTURE, Format);
	if (hr == D3D_OK || hr == D3DOK_NOAUTOGEN)
	{
		bool canAutoGenMips = hr == D3D_OK;

		hr = pD3D->CheckDeviceFormat(nAdapter, DevType, AdapterFormat, D3DUSAGE_QUERY_SRGBREAD, D3DRTYPE_TEXTURE, Format);

		bool canReadSRGB = hr == D3D_OK;
		rd->RecognizePixelFormat(*this, Format, GetD3D9ColorBits(Format), szDescr, canAutoGenMips, canReadSRGB);
	}
  else
    bRes = false;
#endif
  return bRes;
}

void CD3D9Renderer::GetVideoMemoryUsageStats( size_t& vidMemUsedThisFrame, size_t& vidMemUsedRecently, bool bGetPoolsSizes )
{

	if (bGetPoolsSizes)
		vidMemUsedThisFrame = vidMemUsedRecently = (GetTexturesstreampoolsize() + CV_r_rendertargetpoolsize) * 1024 * 1024;

	else {



#if defined (DIRECT3D9)
		// determine front, back and z buffer sizes as they are not registered in the texture manager
		D3DSURFACE_DESC desc;
#if !defined(XENON)
		m_pBackBuffer->GetDesc(&desc);



#endif
		size_t sizeOfFrontBackDepth = desc.Height * desc.Width * GetD3D9ColorBytes(desc.Format) *
			GetD3D9NumSamples(desc.MultiSampleType, desc.MultiSampleQuality) * (1 + m_pd3dpp->BackBufferCount);

		if (m_pd3dpp->EnableAutoDepthStencil)
		{
			m_pZBuffer->GetDesc(&desc);
			sizeOfFrontBackDepth += desc.Height * desc.Width * GetD3D9ColorBytes(desc.Format) * GetD3D9NumSamples(desc.MultiSampleType, desc.MultiSampleQuality);
		}

		// init vid memory usage stats
		vidMemUsedThisFrame = sizeOfFrontBackDepth;
		vidMemUsedRecently = sizeOfFrontBackDepth;

		// add texture usage
		SResourceContainer* pTexContainer( CBaseResource::GetResourcesForClass( CTexture::mfGetClassName() ) );
		if( pTexContainer )
		{
			ResourcesMapItor itEnd( pTexContainer->m_RMap.end() );
			for( ResourcesMapItor it( pTexContainer->m_RMap.begin() ); it != itEnd; ++it )
			{
				CTexture* pTex( static_cast<CTexture*>( it->second ) );
				if( pTex && !pTex->IsNoTexture() )
				{
					if( pTex->m_nAccessFrameID == m_RP.m_TI[m_RP.m_nProcessThreadID].m_nFrameUpdateID )
						vidMemUsedThisFrame += pTex->GetDeviceDataSize();
					if( m_RP.m_TI[m_RP.m_nProcessThreadID].m_nFrameUpdateID - pTex->m_nAccessFrameID < 20 )
						vidMemUsedRecently += pTex->GetDeviceDataSize();
				}
			}
		}	
#else
		assert(!"CD3D9Renderer::GetVideoMemoryUsageStats() not implemented for this platform yet!");
#endif
	}
}

void CD3D9Renderer::RecognizePixelFormat(SPixFormat& Dest, uint32 FormatFromD3D, INT InBitsPerPixel, const char* InDesc, bool bAutoGenMips, bool bCanReadSRGB)
{
	Dest.Init();
	Dest.DeviceFormat  = (D3DFormat)FormatFromD3D;
	Dest.MaxWidth      = 2048;
	Dest.MaxHeight     = 2048;
	Dest.Desc          = InDesc;
	Dest.BitsPerPixel  = InBitsPerPixel;
	Dest.Next          = m_FirstPixelFormat;
	Dest.bCanAutoGenMips = bAutoGenMips;
	Dest.bCanReadSRGB = bCanReadSRGB;
	m_FirstPixelFormat = &Dest;

	if (bAutoGenMips)
		iLog->Log("  Using '%s' pixel texture format (Can autogen mips)", InDesc);
	else
		iLog->Log("  Using '%s' pixel texture format", InDesc);
}

//===========================================================================================

#if defined (DIRECT3D9)

//--------------------------------------------------------------------------------------
// Rejects any D3D9 devices that aren't acceptable to the app by returning false
//--------------------------------------------------------------------------------------
bool CALLBACK CD3D9Renderer::IsD3D9DeviceAcceptable(D3DCAPS9* pCaps, D3DFORMAT AdapterFormat, D3DFORMAT BackBufferFormat, bool bWindowed, void* pUserContext)
{
  // No fallback defined by CryENGINE, so reject any device that doesn't support at least ps.2.0
  if(pCaps->PixelShaderVersion < D3DPS_VERSION(2,0))
    return false;

  // Skip backbuffer formats that don't support alpha blending
  IDirect3D9* pD3D = gcpRendD3D->m_pD3D; 
  if(FAILED(pD3D->CheckDeviceFormat(pCaps->AdapterOrdinal, pCaps->DeviceType, AdapterFormat, D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING, D3DRTYPE_TEXTURE, BackBufferFormat)))
    return false;

  return true;
}

//--------------------------------------------------------------------------------------
// Render the scene using the D3D9 device
//--------------------------------------------------------------------------------------
void CALLBACK CD3D9Renderer::OnD3D9FrameRender(LPDIRECT3DDEVICE9 pd3dDevice, double fTime, float fElapsedTime, void* pUserContext)
{
}


HRESULT CALLBACK CD3D9Renderer::OnD3D9CreateDevice(LPDIRECT3DDEVICE9 pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext)
{
  //assert (DXUTIsCurrentDeviceD3D9());

  CD3D9Renderer *rd = gcpRendD3D;
  rd->m_pd3dDevice = pd3dDevice;
  const D3DCAPS9* pd3dCaps = rd->m_pd3dCaps;

  // Gamma correction support
  if (pd3dCaps->Caps2 & D3DCAPS2_FULLSCREENGAMMA)
    rd->m_Features |= RFT_HWGAMMA;

  IDirect3D9* pD3D = rd->m_pD3D;
#if !defined(XENON) && !defined(PS3)
  DXUTDeviceSettings* pDev = DXUTGetCurrentDeviceSettings();
  CD3D9Enumeration* pd3dEnum = DXUTGetD3D9Enumeration();
  CD3D9EnumDeviceSettingsCombo* pDeviceCombo = pd3dEnum->GetDeviceSettingsCombo(&pDev->d3d9);
  CD3D9EnumAdapterInfo* pAdapterInfo = pd3dEnum->GetAdapterInfo(pDev->d3d9.AdapterOrdinal);




#endif
  D3DADAPTER_IDENTIFIER9 *ai = NULL;

	D3DADAPTER_IDENTIFIER9 adapter_info;
	if (pAdapterInfo)
		ai = &pAdapterInfo->AdapterIdentifier;
	else
	{
		ai = &adapter_info;
		memset(ai,0,sizeof(adapter_info));
		strcpy( ai->Description,"NULL REF" );
		strcpy( ai->DeviceName,"NULL REF" );
		strcpy( ai->Driver,"NULL REF" );
	}

  // Device Id's
  iLog->Log ( "D3D Adapter: Driver name: %s", ai->Driver);

  iLog->Log ( "D3D Adapter: Driver description: %s", ai->Description);
#if !defined(PS3) && !defined(LINUX)
  iLog->Log ( "D3D Adapter: Driver version: %d.%02d.%02d.%04d", HIWORD( ai->DriverVersion.u.HighPart ), LOWORD( ai->DriverVersion.u.HighPart ), HIWORD(ai->DriverVersion.u.LowPart), LOWORD(ai->DriverVersion.u.LowPart));
  // Unique driver/device identifier:
  GUID *pGUID = &ai->DeviceIdentifier;
  iLog->Log ( "D3D Adapter: Driver GUID: %08X-%04X-%04X-%02X%02X%02X%02X%02X%02X%02X%02X", pGUID->Data1, pGUID->Data2, pGUID->Data3, pGUID->Data4[0], pGUID->Data4[1], pGUID->Data4[2], pGUID->Data4[3], pGUID->Data4[4], pGUID->Data4[5], pGUID->Data4[6], pGUID->Data4[7] );
#endif
  iLog->Log ( "D3D Adapter: VendorId = 0x%.4X", ai->VendorId);
  iLog->Log ( "D3D Adapter: DeviceId = 0x%.4X", ai->DeviceId);
  iLog->Log ( "D3D Adapter: SubSysId = 0x%.8X", ai->SubSysId);
  iLog->Log ( "D3D Adapter: Revision = %i", ai->Revision);
  
  // Vendor-specific initializations and workarounds for driver bugs.
  {
    bool ConstrainAspect = 1;
    if(ai->VendorId==4098)
    {
			// ATI
			rd->InitATIAPI();

			rd->m_Features &= ~RFT_HW_MASK;
      rd->m_Features |= RFT_HW_ATI;
      iLog->Log ("D3D Detected: ATI video card");
    }
    else
    if( ai->VendorId==32902 )
    {
      iLog->Log ("D3D Detected: Intel video card");
    }
    else
    if( ai->VendorId==4318 )
    {
			rd->m_Features &= ~RFT_HW_MASK;
			rd->m_Features |= RFT_HW_NVIDIA;
			rd->InitNVAPI();

			iLog->Log ("D3D Detected: NVidia video card");
    }
    else
    if( ai->VendorId==4139 )
    {
      iLog->Log ("D3D Detected: Matrox video card");
    }
    else
    if( ai->VendorId==0x18ca )
    {
      iLog->Log ("D3D Detected: XGI video card");
    }
    else
    {
      iLog->Log ("D3D Detected: Generic 3D accelerator");
    }
  }

  // Set viewport.
#if defined(WIN32) || defined(WIN64)
  rd->m_pRT->RC_SetViewport(0, 0, rd->GetWidth(), rd->GetHeight());
#else
  rd->RT_SetViewport(0, 0, rd->GetWidth(), rd->GetHeight());
#endif
	rd->m_MainViewport.nX = 0;
	rd->m_MainViewport.nY = 0;
	rd->m_MainViewport.nWidth = rd->GetWidth();
	rd->m_MainViewport.nHeight = rd->GetHeight();
	rd->m_MainRTViewport.nX = 0;
	rd->m_MainRTViewport.nY = 0;
	rd->m_MainRTViewport.nWidth = rd->GetWidth();
	rd->m_MainRTViewport.nHeight = rd->GetHeight();

	// Check multitexture caps.
	iLog->Log ("D3D Driver: FFP MaxTextureBlendStages   = %i", pd3dCaps->MaxTextureBlendStages);
	iLog->Log ("D3D Driver: FFP MaxSimultaneousTextures = %i", pd3dCaps->MaxSimultaneousTextures);
	rd->m_numtmus = 16; //di->Caps.MaxSimultaneousTextures;

  // Handle the texture formats we need.
  {
    // Find the needed texture formats.
    {
		rd->m_FirstPixelFormat = NULL;

		// RGB uncompressed unsigned formats
		rd->m_FormatA8R8G8B8.CheckSupport(D3DFMT_A8R8G8B8, "A8R8G8B8");
		rd->m_FormatA2R10G10B10.CheckSupport(D3DFMT_A2R10G10B10, "A2R10G10B10");
			//rd->m_FormatA2R10G10B10.CheckSupport(D3DFMT_A2B10G10R10, "A2B10G10R10");
		rd->m_FormatX8R8G8B8.CheckSupport(D3DFMT_X8R8G8B8, "X8R8G8B8");
#if !defined(XENON)
		rd->m_FormatR8G8B8.CheckSupport(D3DFMT_R8G8B8, "R8G8B8");
#endif

		rd->m_FormatA4R4G4B4.CheckSupport(D3DFMT_A4R4G4B4, "A4R4G4B4");
		rd->m_FormatR5G6B5.CheckSupport(D3DFMT_R5G6B5, "R5G6B5");

		// Alpha formats
		rd->m_FormatA8.CheckSupport(D3DFMT_A8, "A8");

		rd->m_FormatA8L8.CheckSupport(D3DFMT_A8L8, "A8L8");
		rd->m_FormatL8.CheckSupport(D3DFMT_L8, "L8");

		  // Fat RGB uncompressed unsigned formats
		rd->m_FormatA16B16G16R16F.CheckSupport(D3DFMT_A16B16G16R16F, "A16B16G16R16F");
		rd->m_FormatA16B16G16R16.CheckSupport(D3DFMT_A16B16G16R16, "A16B16G16R16");
		rd->m_FormatG16R16F.CheckSupport(D3DFMT_G16R16F, "G16R16F");
		rd->m_FormatG16R16.CheckSupport(D3DFMT_G16R16, "G16R16");
		rd->m_FormatV16U16.CheckSupport(D3DFMT_V16U16, "V16U16");
		rd->m_FormatR16F.CheckSupport(D3DFMT_R16F, "R16F");
		rd->m_FormatR32F.CheckSupport(D3DFMT_R32F, "R32F");
		rd->m_FormatA32B32G32R32F.CheckSupport(D3DFMT_A32B32G32R32F, "A32B32G32R32F");

		// RGB compressed unsigned formats
		rd->m_FormatDXT1.CheckSupport(D3DFMT_DXT1, "DXT1");
		rd->m_FormatDXT3.CheckSupport(D3DFMT_DXT3, "DXT3");
		rd->m_FormatDXT5.CheckSupport(D3DFMT_DXT5, "DXT5");
		rd->m_Format3Dc.CheckSupport(D3DFMT_3DC, "3DC");

      // Depth formats
#if defined(INVERT_DEPTH_RANGE)
		rd->m_FormatDepth24.CheckSupport(D3DFMT_D24FS8, "D24FS8");
#else
		rd->m_FormatDepth24.CheckSupport(D3DFMT_D24S8, "D24S8");
#endif
		rd->m_FormatDepth16.CheckSupport(D3DFMT_D16, "D16");
			//ATI DST formats
		{
			//rd->m_FormatDF16.CheckSupport(D3DFMT_DF16, "DF16");
			//rd->m_bDeviceSupports_ATI_DF16 = rd->m_FormatDF16.IsValid();
			rd->m_FormatDF24.CheckSupport(D3DFMT_DF24, "DF24", eTXUSAGE_DEPTHSTENCIL);
			rd->m_bDeviceSupports_ATI_DF24 = rd->m_FormatDF24.IsValid();

			rd->m_FormatDF16.CheckSupport(D3DFMT_DF16, "DF16", eTXUSAGE_DEPTHSTENCIL);
		}

		//NVIDIA NULL Format
		{
			rd->m_FormatNULL.CheckSupport(D3DFMT_NULL, "NULL", eTXUSAGE_RENDERTARGET);
		}

		//NVIDIA native depth buffers
		{
			rd->m_FormatD16.CheckSupport(D3DFMT_D16, "D16", eTXUSAGE_DEPTHSTENCIL);
			rd->m_FormatD24S8.CheckSupport(D3DFMT_D24S8, "D24S8", eTXUSAGE_DEPTHSTENCIL);
		}
      
		//NVIDIA DBT
		{
			rd->m_bDeviceSupports_NVDBT = SUCCEEDED( pD3D->CheckDeviceFormat( pDeviceCombo->AdapterOrdinal, pDeviceCombo->DeviceType, pDeviceCombo->AdapterFormat, 0, D3DRTYPE_SURFACE, (D3DFORMAT)MAKEFOURCC('N','V','D','B') ) );
		}
      
		if (rd->m_FormatDXT1.IsValid() || rd->m_FormatDXT3.IsValid() || rd->m_FormatDXT5.IsValid())
			rd->m_Features |= RFT_COMPRESSTEXTURE;
    }
  }

  rd->m_MaxAnisotropyLevel = 1;
  // Check the device for supported filtering methods
  if( pd3dCaps->RasterCaps & D3DPRASTERCAPS_ANISOTROPY )
  {
    rd->m_MaxAnisotropyLevel = pd3dCaps->MaxAnisotropy;
    iLog->Log ("D3D Driver: Supports MaxAnisotropy level %d", rd->m_MaxAnisotropyLevel); 
    rd->m_Features |= RFT_ALLOWANISOTROPIC;
  }
  rd->m_MaxAnisotropyLevel = min(rd->m_MaxAnisotropyLevel, CRenderer::CV_r_texmaxanisotropy);

  iLog->Log ("D3D Driver: Textures (%ix%i)-(%ix%i), Max aspect %i", 8, 8, pd3dCaps->MaxTextureWidth, pd3dCaps->MaxTextureHeight, pd3dCaps->MaxTextureAspectRatio);

  // Init render states.
#if !defined(XENON) && !defined(PS3)
  {
    rd->m_RP.m_eCull = eCULL_None;
    pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
    pd3dDevice->SetRenderState(D3DRS_ALPHAREF, 0);
    pd3dDevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATER);
    pd3dDevice->SetRenderState(D3DRS_FILLMODE,  D3DFILL_SOLID);
    pd3dDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
    pd3dDevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
    pd3dDevice->SetRenderState(D3DRS_ZENABLE, FALSE);
    pd3dDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
    pd3dDevice->SetRenderState(D3DRS_DITHERENABLE, TRUE);
    pd3dDevice->SetPixelShader(NULL);
		for(uint32 id=0;id<RT_COMMAND_BUF_COUNT;++id)
			rd->m_RP.m_TI[id].m_FS.m_bEnable = false;

    // Set default stencil states
    rd->m_RP.m_CurStencilState = 0;
		rd->m_RP.m_CurStencMask = 0xffffffff;
    rd->m_RP.m_CurStencWriteMask = 0xFFFFFFFF;
    rd->m_RP.m_CurStencRef = 0;
    rd->m_RP.m_CurStencilRefAndMask = 0;
		rd->m_RP.m_CurStencilCullFunc = FSS_STENCFUNC_ALWAYS;

    pd3dDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
    if (pd3dCaps->StencilCaps & D3DSTENCILCAPS_TWOSIDED)
    {
#ifndef PS3
      pd3dDevice->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, FALSE);
#endif
      pd3dDevice->SetRenderState(D3DRS_CCW_STENCILFAIL, D3DSTENCILOP_KEEP);
      pd3dDevice->SetRenderState(D3DRS_CCW_STENCILZFAIL, D3DSTENCILOP_KEEP);
      pd3dDevice->SetRenderState(D3DRS_CCW_STENCILPASS, D3DSTENCILOP_KEEP);
      pd3dDevice->SetRenderState(D3DRS_CCW_STENCILFUNC, D3DCMP_ALWAYS);
    }
    pd3dDevice->SetRenderState(D3DRS_STENCILMASK, 0xffffffff);
    pd3dDevice->SetRenderState(D3DRS_STENCILWRITEMASK, 0xFFFFFFFF);
    pd3dDevice->SetRenderState(D3DRS_STENCILREF, 0);

    pd3dDevice->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP);
    pd3dDevice->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP);
    pd3dDevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_KEEP);
    pd3dDevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
  }
#endif

  rd->msCurState = GS_DEPTHWRITE | GS_NODEPTHTEST;
	for(uint32 id=0;id<RT_COMMAND_BUF_COUNT;++id)
	{
		rd->m_RP.m_TI[id].m_eCurColorOp = eCO_DISABLE;
		rd->m_RP.m_TI[id].m_eCurColorArg = 255;
		rd->m_RP.m_TI[id].m_eCurAlphaArg = 255;
	}

#if !defined(XENON) && !defined(PS3)
  int i;
  // Init texture stage state.
  {
    //FLOAT LodBias=-0.5;
    //pd3dDevice->SetSamplerState( 0, D3DSAMP_MIPMAPLODBIAS, *(DWORD*)&LodBias );
    pd3dDevice->SetSamplerState(0, D3DSAMP_ADDRESSU,   D3DTADDRESS_WRAP);
    pd3dDevice->SetSamplerState(0, D3DSAMP_ADDRESSV,   D3DTADDRESS_WRAP);
    rd->EF_SetColorOp(eCO_MODULATE, eCO_MODULATE, DEF_TEXARG0, DEF_TEXARG0);
    pd3dDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
    pd3dDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
    pd3dDevice->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
    CTexture::s_TexStages[0].m_State.m_nMinFilter = D3DTEXF_LINEAR;
    CTexture::s_TexStages[0].m_State.m_nMagFilter = D3DTEXF_LINEAR;
    CTexture::s_TexStages[0].m_State.m_nMipFilter = D3DTEXF_LINEAR;

    for (i=1; i<rd->m_numtmus; i++)
    {
      // Set stage i state.
      pd3dDevice->SetSamplerState(i, D3DSAMP_ADDRESSU,  D3DTADDRESS_WRAP);
      pd3dDevice->SetSamplerState(i, D3DSAMP_ADDRESSV,  D3DTADDRESS_WRAP);
      rd->EF_SetColorOp(eCO_DISABLE, eCO_DISABLE, DEF_TEXARG1, DEF_TEXARG1);
      pd3dDevice->SetSamplerState(i, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
      pd3dDevice->SetSamplerState(i, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
      pd3dDevice->SetSamplerState(i, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
      CTexture::s_TexStages[i].m_State.m_nMinFilter = D3DTEXF_LINEAR;
      CTexture::s_TexStages[i].m_State.m_nMagFilter = D3DTEXF_LINEAR;
      CTexture::s_TexStages[i].m_State.m_nMipFilter = D3DTEXF_LINEAR;
    }
  }
#endif

  // Check to see if device supports visibility query
  IDirect3DQuery9 *pOcclQuery = 0;;
  if (D3DERR_NOTAVAILABLE == pd3dDevice->CreateQuery (D3DQUERYTYPE_OCCLUSION, &pOcclQuery))
    rd->m_Features &= ~RFT_OCCLUSIONTEST;
  else
  {
    rd->m_Features |= RFT_OCCLUSIONTEST;
    pOcclQuery->Release();
  }

  CTexture::SetDefTexFilter(CV_d3d9_texturefilter->GetString());

  // For safety, lots of drivers don't handle tiny texture sizes too tell.
#if defined(WIN32) || defined(WIN64)
	typedef HRESULT (WINAPI *FP_DirectDrawCreate)(GUID FAR*, LPDIRECTDRAW FAR* , IUnknown*);		
	FP_DirectDrawCreate pddc((FP_DirectDrawCreate) GetProcAddress(LoadLibrary("ddraw.dll"), "DirectDrawCreate"));		
	IDirectDraw* pDD(0);
	if (pddc)
		pddc(0, &pDD, 0);
	rd->m_MaxTextureMemory = 0;
	if (pDD)
	{
		IDirectDraw7* pDD7(0);
		if (SUCCEEDED(pDD->QueryInterface(IID_IDirectDraw7, (void**) &pDD7)) && pDD7)
		{
			DDSCAPS2 sDDSCaps2;
			ZeroMemory(&sDDSCaps2, sizeof(sDDSCaps2));
			sDDSCaps2.dwCaps = DDSCAPS_LOCALVIDMEM;

			unsigned long localMem(0);
			pDD7->GetAvailableVidMem(&sDDSCaps2, &localMem, 0);
			SAFE_RELEASE(pDD7);
			rd->m_MaxTextureMemory = localMem;
		}
		SAFE_RELEASE(pDD);
	}
#else
	rd->m_MaxTextureMemory = pd3dDevice->GetAvailableTextureMem();
#endif
  if (CRenderer::CV_r_texturesstreampoolsize <= 0)
    CRenderer::CV_r_texturesstreampoolsize = (int)(rd->m_MaxTextureMemory/1024.0f/1024.0f*0.75f);

  rd->m_MaxTextureSize = min(pd3dCaps->MaxTextureHeight, pd3dCaps->MaxTextureWidth); //min(wdt, hgt);

	rd->m_bDeviceSupportsR16FRendertarget = SUCCEEDED(pD3D->CheckDeviceFormat(pDeviceCombo->AdapterOrdinal, pDeviceCombo->DeviceType, pDeviceCombo->AdapterFormat, D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, D3DFMT_R16F));

#ifndef XENON
	rd->m_bDeviceSupportsVertexTexture = SUCCEEDED(pD3D->CheckDeviceFormat(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, pDeviceCombo->AdapterFormat, D3DUSAGE_QUERY_VERTEXTEXTURE, D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F));


#endif

#ifndef XENON
	rd->m_bDeviceSupportsR2VB = SUCCEEDED(pD3D->CheckDeviceFormat(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, pDeviceCombo->AdapterFormat, 0, D3DRTYPE_SURFACE, (D3DFORMAT) MAKEFOURCC('R','2','V','B')));
	rd->m_bDeviceSupportsR2VB &= D3DSHADER_VERSION_MAJOR(pd3dCaps->PixelShaderVersion) >= 3;


#endif





  if( rd->m_bDeviceSupportsVertexTexture)
    rd->m_Features |= RFT_HW_VERTEXTEXTURES;

	if( rd->m_bDeviceSupportsR2VB)
		rd->m_Features |= RFT_HW_R2VB;

	PREFAST_SUPPRESS_WARNING(6326)
	rd->m_bUseWaterTessHW = CV_r_WaterTessellationHW != 0;

  DWORD msQuality;
#if !defined(XENON) && !defined(PS3)
	if (pDeviceCombo->DeviceType != D3DDEVTYPE_NULLREF)		// to prevent crash
#endif
	{
		if (SUCCEEDED(pD3D->CheckDeviceMultiSampleType( pDeviceCombo->AdapterOrdinal, 
			pDeviceCombo->DeviceType, D3DFMT_G16R16F, 
			pDeviceCombo->Windowed, D3DMULTISAMPLE_4_SAMPLES, &msQuality ) ) )
		{
			rd->m_bDeviceSupports_G16R16_MSAA = true;
		}
		if (SUCCEEDED(pD3D->CheckDeviceMultiSampleType( pDeviceCombo->AdapterOrdinal, 
			pDeviceCombo->DeviceType, D3DFMT_A16B16G16R16F, 
			pDeviceCombo->Windowed, D3DMULTISAMPLE_4_SAMPLES, &msQuality ) ) )
		{
			rd->m_bDeviceSupports_A16B16G16R16_MSAA = true;
		}
	}

  rd->m_bDeviceSupportsInstancing = (D3DSHADER_VERSION_MAJOR(pd3dCaps->VertexShaderVersion) >= 3);
  if (!rd->m_bDeviceSupportsInstancing)
  {
    D3DFORMAT instanceSupport = (D3DFORMAT)MAKEFOURCC('I', 'N', 'S', 'T');
    if(SUCCEEDED(pD3D->CheckDeviceFormat(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, 0, D3DRTYPE_SURFACE, instanceSupport)))
    {
      rd->m_bDeviceSupportsInstancing = 2;
      // Notify the driver that instancing support is expected
      pd3dDevice->SetRenderState(D3DRS_POINTSIZE, instanceSupport);
    }
  }
  rd->m_bDeviceSupportsFP16Separate = (pd3dCaps->NumSimultaneousRTs>=4) && SUCCEEDED(pD3D->CheckDeviceFormat(pDeviceCombo->AdapterOrdinal, pDeviceCombo->DeviceType, pDeviceCombo->AdapterFormat, D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, D3DFMT_G16R16F));
  // Don't use separate bit planes anymore
  rd->m_bDeviceSupportsFP16Separate = false;

  rd->m_bDeviceSupportsFP16Filter = true;
  rd->m_bDeviceSupportsG16R16Filter = false;
  int nHDRSupported = 1;
  rd->m_HDR_FloatFormat_Scalar = eTF_R32F;//eTF_R16F;
  rd->m_HDR_FloatFormat = eTF_A16B16G16R16F;

  if(FAILED(pD3D->CheckDeviceFormat(pDeviceCombo->AdapterOrdinal, pDeviceCombo->DeviceType, pDeviceCombo->AdapterFormat, D3DUSAGE_RENDERTARGET | D3DUSAGE_QUERY_FILTER, D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)))
    rd->m_bDeviceSupportsFP16Filter = false;
  if(FAILED(pD3D->CheckDeviceFormat(pDeviceCombo->AdapterOrdinal, pDeviceCombo->DeviceType, pDeviceCombo->AdapterFormat, D3DUSAGE_RENDERTARGET | D3DUSAGE_QUERY_FILTER, D3DRTYPE_TEXTURE, D3DFMT_G16R16F)))
    rd->m_bDeviceSupportsFP16Filter = false;





  if(SUCCEEDED(pD3D->CheckDeviceFormat(pDeviceCombo->AdapterOrdinal, pDeviceCombo->DeviceType, pDeviceCombo->AdapterFormat, D3DUSAGE_RENDERTARGET | D3DUSAGE_QUERY_FILTER, D3DRTYPE_TEXTURE, D3DFMT_G16R16)))
    rd->m_bDeviceSupportsG16R16Filter = true;





#if defined(WIN32) || defined(WIN64)
	if (CV_r_shadersps3)
  {
    rd->m_bDeviceSupportsFP16Filter = true;
    rd->m_bDeviceSupportsG16R16Filter = true;
  }
#endif

  {
    // Check support for HDR rendering
		if (rd->m_FormatR32F.IsValid())
      rd->m_HDR_FloatFormat_Scalar = eTF_R32F;
		else
			rd->m_HDR_FloatFormat_Scalar = eTF_R16F;

		if(FAILED(pD3D->CheckDeviceFormat(pDeviceCombo->AdapterOrdinal, pDeviceCombo->DeviceType, pDeviceCombo->AdapterFormat, D3DUSAGE_RENDERTARGET | D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING, D3DRTYPE_SURFACE, D3DFMT_A16B16G16R16F)))
      nHDRSupported = 0;
    else
    if(FAILED(pD3D->CheckDeviceFormat(pDeviceCombo->AdapterOrdinal, pDeviceCombo->DeviceType, pDeviceCombo->AdapterFormat, D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, D3DFMT_R16F)))
    {
      rd->m_HDR_FloatFormat_Scalar = eTF_R32F;
      if(FAILED(pD3D->CheckDeviceFormat(pDeviceCombo->AdapterOrdinal, pDeviceCombo->DeviceType, pDeviceCombo->AdapterFormat, D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, D3DFMT_R32F)))
        nHDRSupported = 0;
    }

    if (!nHDRSupported && pd3dCaps->NumSimultaneousRTs>=2 && (pd3dCaps->PrimitiveMiscCaps & D3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING) && D3DSHADER_VERSION_MAJOR(pd3dCaps->PixelShaderVersion) >= 2)
    {
      nHDRSupported = 2;
      rd->m_bDeviceSupportsFP16Separate = false;
      if(FAILED(pD3D->CheckDeviceFormat(pDeviceCombo->AdapterOrdinal, pDeviceCombo->DeviceType, pDeviceCombo->AdapterFormat, D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)))
        nHDRSupported = 3;
      else
      if(FAILED(pD3D->CheckDeviceFormat(pDeviceCombo->AdapterOrdinal, pDeviceCombo->DeviceType, pDeviceCombo->AdapterFormat, D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, D3DFMT_R16F)))
      {
        rd->m_HDR_FloatFormat_Scalar = eTF_R32F;
        if(FAILED(pD3D->CheckDeviceFormat(pDeviceCombo->AdapterOrdinal, pDeviceCombo->DeviceType, pDeviceCombo->AdapterFormat, D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, D3DFMT_R32F)))
          nHDRSupported = 3;
      }
    }
  }












  if (!nHDRSupported)
  {
#if defined(USE_HDR) && !defined(CONSOLE_CONST_CVAR_MODE)
    CV_r_HDRRendering = 0;
#endif
    rd->m_Features &= ~RFT_HW_HDR;
  }
  else
    rd->m_Features |= RFT_HW_HDR;

	iLog->Log(" Renderer HDR_Scalar: %s",CTexture::NameForTextureFormat(rd->m_HDR_FloatFormat_Scalar));
  
  rd->m_nHDRType = nHDRSupported;








  rd->m_DepthBufferOrig.pSurf = rd->m_pZBuffer;
  rd->m_DepthBufferOrig.nWidth = rd->m_d3dsdBackBuffer.Width;
  rd->m_DepthBufferOrig.nHeight = rd->m_d3dsdBackBuffer.Height;
  rd->m_DepthBufferOrig.bBusy = true;
  rd->m_DepthBufferOrig.nFrameAccess = -2;

  rd->m_DepthBufferOrigMSAA.pSurf = rd->m_pZBuffer;
  rd->m_DepthBufferOrigMSAA.nWidth = rd->m_d3dsdBackBuffer.Width;
  rd->m_DepthBufferOrigMSAA.nHeight = rd->m_d3dsdBackBuffer.Height;
  rd->m_DepthBufferOrigMSAA.bBusy = true;
  rd->m_DepthBufferOrigMSAA.nFrameAccess = -2;

#if !defined(XENON) && !defined(PS3)
  pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL, 0, 1.0f, 0);
#endif
	
	for(TListRendererEventListeners::iterator iter=rd->m_listRendererEventListeners.begin(); iter!=rd->m_listRendererEventListeners.end(); ++iter)
	{
		(*iter)->OnPostCreateDevice();
	}

  return S_OK;
}

inline bool CompareTexs(const CTexture *a, const CTexture *b)
{
  return (a->GetPriority() > b->GetPriority());
}


























































































//--------------------------------------------------------------------------------------
// Create any D3D9 resources that will live through a device reset (D3DPOOL_MANAGED)
// and aren't tied to the back buffer size 
//--------------------------------------------------------------------------------------
HRESULT CALLBACK CD3D9Renderer::OnD3D9ResetDevice(LPDIRECT3DDEVICE9 pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext)
{
	MEMSTAT_LABEL("D3D9ResetDevice");

  HRESULT hr = S_OK;
  uint32 i, j;

  //InitTexFillers();
  //Flush();

  //iLog->Log("...RestoreDeviceObjects");
  CD3D9Renderer *rd = gcpRendD3D;
  
  float fPAR = 1.0f;








  pd3dDevice->GetDepthStencilSurface(&rd->m_pZBuffer);
	if (rd->m_pZBuffer)
	{
		D3DSURFACE_DESC Desc;
		rd->m_pZBuffer->GetDesc(&Desc);
		rd->m_ZFormat = Desc.Format;
	}
	else
		rd->m_ZFormat = D3DFMT_UNKNOWN;




























  pd3dDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &rd->m_pBackBuffer);
  if (rd->m_pBackBuffer)
    rd->m_pBackBuffer->GetDesc(&rd->m_d3dsdBackBuffer);

  if( rd->GetS3DRend().GetStereoDevice() == STEREO_DEVICE_DUALHEAD )
  {
    pd3dDevice->GetBackBuffer(1, 0, D3DBACKBUFFER_TYPE_MONO, &rd->m_pSecondBackBuffer);
  }


	rd->SetPixelAspectRatio(fPAR);
	
  rd->m_nRTStackLevel[0] = 0;
  rd->m_RTStack[0][0].m_pDepth = rd->m_pZBuffer;
  rd->m_RTStack[0][0].m_pSurfDepth = &rd->m_DepthBufferOrig;
  rd->m_RTStack[0][0].m_pTarget = rd->m_pBackBuffer;
  rd->m_RTStack[0][0].m_Width = rd->m_d3dsdBackBuffer.Width;
  rd->m_RTStack[0][0].m_Height = rd->m_d3dsdBackBuffer.Height;
  rd->m_RTStack[0][0].m_pTex = CTexture::s_pBackBuffer;
  rd->m_RTStack[0][0].m_bScreenVP = true;
  //CTexture::m_pBackBuffer->SetFlags(FT_USAGE_PREDICATED_TILING);


  for (i=0; i<RT_STACK_WIDTH; i++)
  {
    rd->m_pNewTarget[i] = &rd->m_RTStack[i][0];
    rd->m_pCurTarget[i] = rd->m_pNewTarget[0]->m_pTex;
  }







  rd->m_DepthBufferOrig.pSurf = rd->m_pZBuffer;
  rd->m_DepthBufferOrig.nWidth = rd->m_d3dsdBackBuffer.Width;
  rd->m_DepthBufferOrig.nHeight = rd->m_d3dsdBackBuffer.Height;
  rd->m_DepthBufferOrig.bBusy = true;
  rd->m_DepthBufferOrig.nFrameAccess = -2;

  rd->m_DepthBufferOrigMSAA.pSurf = rd->m_pZBuffer;
  rd->m_DepthBufferOrigMSAA.nWidth = rd->m_d3dsdBackBuffer.Width;
  rd->m_DepthBufferOrigMSAA.nHeight = rd->m_d3dsdBackBuffer.Height;
  rd->m_DepthBufferOrigMSAA.bBusy = true;
  rd->m_DepthBufferOrigMSAA.nFrameAccess = -2;

	rd->m_DevMan.AssignDevice(rd->m_pd3dDevice);
  {
		MEMSTAT_CONTEXT(EMemStatContextTypes::MSC_D3D, 0, "D3D Dynamic IndexBuffer");
    hr = rd->m_DynIB.CreateIB(rd->m_pd3dDevice, 65536);
    if (FAILED(hr))
      return hr;
  }

	//////////////////////////////////////////////////////////////////////////
	{
		MEMSTAT_CONTEXT(EMemStatContextTypes::MSC_D3D, 0, "D3D Query");

		hr = pd3dDevice->CreateQuery(D3DQUERYTYPE_EVENT, &rd->m_pQuery[0]);
		if(hr != D3DERR_NOTAVAILABLE)
		{
			assert(rd->m_pQuery[0]);
			rd->m_pQuery[0]->Issue(D3DISSUE_END);
			hr = pd3dDevice->CreateQuery(D3DQUERYTYPE_EVENT, &rd->m_pQuery[1]);
			rd->m_pQuery[1]->Issue(D3DISSUE_END);
		}
		hr = pd3dDevice->CreateQuery(D3DQUERYTYPE_EVENT, &rd->m_pQueryPerf);
		rd->m_pQueryPerf->Issue(D3DISSUE_END);
		hr = pd3dDevice->CreateQuery(D3DQUERYTYPE_EVENT, &rd->m_pHDRLumQuery);
		if(hr != D3DERR_NOTAVAILABLE)
		{
			assert(rd->m_pHDRLumQuery);
			rd->m_pHDRLumQuery->Issue(D3DISSUE_END);
		}

		rd->m_OcclQueries.Reserve(MAX_OCCL_QUERIES);
		for (j=0; j<MAX_OCCL_QUERIES; j++)
		{
			rd->m_OcclQueries[j].Create();
		}
		rd->m_OcclQueriesUsed = 0;
	}
	//////////////////////////////////////////////////////////////////////////

  for (j=0; j<POOL_MAX; j++)
  {
		MEMSTAT_CONTEXT(EMemStatContextTypes::MSC_D3D, 0, "D3D Dynamic VertexBuffer");
    int nVertSize, nVerts;
    switch (j)
    {
      case POOL_P3F_COL4UB_TEX2F:
      default:
        nVerts = MAX_DYNVB3D_VERTS;
        nVertSize = sizeof(SVF_P3F_C4B_T2F);
        break;
      case POOL_TRP3F_COL4UB_TEX2F:
        nVerts = 32768;
        nVertSize = sizeof(SVF_TP3F_C4B_T2F);
        break;
      case POOL_TRP3F_TEX2F_TEX3F:
        nVerts = 4096;
        nVertSize = sizeof(SVF_TP3F_T2F_T3F);
        break;
      case POOL_P3F_TEX3F:
        nVerts = 16384;
        nVertSize = sizeof(SVF_P3F_T3F);
        break;
			case POOL_P3F_TEX2F_TEX3F:
				nVerts = 1024;
				nVertSize = sizeof(SVF_P3F_T2F_T3F);
				break;
    }
    rd->m_DynVB[j].CreateVB(rd->m_pd3dDevice, nVerts, nVertSize);
  }

  rd->CreateAuxiliaryMeshes();

  rd->EF_Restore();

	//////////////////////////////////////////////////////////////////////////
	{
		MEMSTAT_CONTEXT(EMemStatContextTypes::MSC_Other, 0, "Renderer ReloadTextures");

		SResourceContainer *pRL = CBaseResource::GetResourcesForClass(CTexture::mfGetClassName());
		TArray<CTexture *> Texs;
		if (pRL)
		{
			ResourcesMapItor itor;
			for (itor=pRL->m_RMap.begin(); itor!=pRL->m_RMap.end(); itor++)
			{
				CTexture *tp = (CTexture *)itor->second;
				if (!tp || tp->IsNoTexture())
					continue;
				if (!tp->IsNeedRestoring())
					continue;
				Texs.AddElem(tp);
			}
		}
		rd->m_bDeviceLost = 0;
		if (Texs.Num())
		{
			std::sort(&Texs[0], &Texs[0]+Texs.Num(), CompareTexs);
			ColorF col = ColorF(0,1,0,0);
			for (i=0; i<Texs.Num(); i++)
			{
				CTexture *tp = Texs[i];
				tp->ResetNeedRestoring();
				tp->Reload();
			}
		}
	}

  rd->m_RP.m_eCull = eCULL_None;
  pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);

  //m_pd3dDevice->SetRenderState( D3DRS_AMBIENT, 0xffffffff );
  // ATI instancing
#if !defined(XENON) && !defined(PS3)
  if (rd->m_bDeviceSupportsInstancing == 2)
  {
    // Notify the driver that instancing support is expected
    D3DFORMAT instanceSupport = (D3DFORMAT)MAKEFOURCC('I', 'N', 'S', 'T');
    rd->m_pd3dDevice->SetRenderState(D3DRS_POINTSIZE, instanceSupport);
  }
#endif

  rd->m_pLastVDeclaration = NULL;

#if defined(ENABLE_RENDER_AUX_GEOM)
	if (rd->m_pRenderAuxGeomD3D && FAILED(hr=rd->m_pRenderAuxGeomD3D->RestoreDeviceObjects()))
		return hr;
#endif

  rd->m_MSAA = 0;

	for(TListRendererEventListeners::iterator iter=rd->m_listRendererEventListeners.begin(); iter!=rd->m_listRendererEventListeners.end(); ++iter)
	{
		(*iter)->OnPostResetDevice();
	}

  for (i=0; i<MAX_TMU; i++)
  {
    pd3dDevice->SetSamplerState(i, D3DSAMP_ADDRESSU,  D3DTADDRESS_WRAP);
    pd3dDevice->SetSamplerState(i, D3DSAMP_ADDRESSV,  D3DTADDRESS_WRAP);
    pd3dDevice->SetSamplerState(i, D3DSAMP_ADDRESSW,  D3DTADDRESS_WRAP);
    rd->EF_SetColorOp(eCO_DISABLE, eCO_DISABLE, DEF_TEXARG1, DEF_TEXARG1);
    pd3dDevice->SetSamplerState(i, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
    pd3dDevice->SetSamplerState(i, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
    pd3dDevice->SetSamplerState(i, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
    CTexture::s_TexStages[i].m_State.m_nMinFilter = D3DTEXF_LINEAR;
    CTexture::s_TexStages[i].m_State.m_nMagFilter = D3DTEXF_LINEAR;
    CTexture::s_TexStages[i].m_State.m_nMipFilter = D3DTEXF_LINEAR;
    CTexture::s_TexStages[i].m_State.m_nAddressU = D3DTADDRESS_WRAP;
    CTexture::s_TexStages[i].m_State.m_nAddressV = D3DTADDRESS_WRAP;
    CTexture::s_TexStages[i].m_State.m_nAddressW = D3DTADDRESS_WRAP;
    CTexture::s_TexStages[i].m_State.m_nAnisotropy = 1;
  }

	CHWShader::m_pCurVS = 0;
	CHWShader::m_pCurPS = 0;











  return S_OK;
}

//--------------------------------------------------------------------------------------
// Release D3D9 resources created in the OnD3D9ResetDevice callback 
//--------------------------------------------------------------------------------------
void CALLBACK CD3D9Renderer::OnD3D9LostDevice(void* pUserContext)
{
	MEMSTAT_LABEL("D3D9LostDevice");

  uint32 i = 0;
  uint32 j;

  CD3D9Renderer *rd = gcpRendD3D;

  rd->FX_Invalidate();

#ifndef EXCLUDE_SCALEFORM_SDK
  rd->SF_ResetResources();
#endif

  rd->m_nFrameReset++;

  SAFE_RELEASE(rd->m_pQuery[0]);
  SAFE_RELEASE(rd->m_pQuery[1]);
  SAFE_RELEASE(rd->m_pQueryPerf);
  SAFE_RELEASE(rd->m_pHDRLumQuery);
  rd->m_DynIB.Release();
  for (j=0; j<POOL_MAX; j++)
  {
    rd->m_DynVB[j].Release();
  }
  for (j=0; j<rd->m_OcclQueries.size(); j++)
  {
    rd->m_OcclQueries[j].Release();
  }

  rd->ReleaseAuxiliaryMeshes();
  /*SAFE_RELEASE(rd->m_pUnitFrustumVB[i]);
  SAFE_RELEASE(rd->m_pUnitFrustumIB[i]);

  SAFE_RELEASE(rd->m_pUnitSphereVB);
  SAFE_RELEASE(rd->m_pUnitSphereIB);*/

  byte bDL = rd->m_bDeviceLost;
  rd->m_bDeviceLost = 0;
  // Unload vertex/index buffers
	{ AUTO_LOCK(CRenderMesh::m_sLinkLock);
  for (SIntrusiveList *iter = CRenderMesh::m_MeshList.next; iter != &CRenderMesh::m_MeshList; iter = iter->next)
	{
		iter->entry<CRenderMesh, &CRenderMesh::m_Chain>()->FreeDeviceBuffers(true); 
	}}

  CRendElement *pRE = CRendElement::m_RootGlobal.m_NextGlobal;
  while (pRE != &CRendElement::m_RootGlobal)
  {
    if( pRE->mfGetType() != eDATA_PostProcess )
      pRE->mfReset();

    pRE = pRE->m_NextGlobal;
  }
  rd->m_bDeviceLost = bDL;

  for (i=0; i<MAX_CONSTANTS_VS; i++)
  {
    CHWShader_D3D::m_CurVSParams[i].x = -99999.9f;
    CHWShader_D3D::m_CurVSParams[i].y = -99999.9f;
    CHWShader_D3D::m_CurVSParams[i].z = -99999.9f;
    CHWShader_D3D::m_CurVSParams[i].w = -99999.9f;
  }
  for (i=0; i<MAX_CONSTANTS_PS; i++)
  {
    CHWShader_D3D::m_CurPSParams[i].x = -99999.9f;
    CHWShader_D3D::m_CurPSParams[i].y = -99999.9f;
    CHWShader_D3D::m_CurPSParams[i].z = -99999.9f;
    CHWShader_D3D::m_CurPSParams[i].w = -99999.9f;
  }
  SResourceContainer *pRL = CBaseResource::GetResourcesForClass(CTexture::mfGetClassName());
  if (pRL)
  {
    ResourcesMapItor itor;
    for (itor=pRL->m_RMap.begin(); itor!=pRL->m_RMap.end(); itor++)
    {
      CTexture *tp = (CTexture *)itor->second;
      if (!CTexture::IsTextureExist(tp) || tp->IsNoTexture() )
        continue;
      D3DPOOL Pool = tp->GetPool();
      if (Pool != D3DPOOL_DEFAULT)
        continue;

      tp->ReleaseDeviceTexture(false);
      tp->SetNeedRestoring();
    }
  }
  for (i=0; i<rd->m_TempDepths.Num(); i++)
  {
    SD3DSurface *pS = rd->m_TempDepths[i];
    if (pS)
    {
      pS->Release();
      delete pS;
    }
  }
  rd->m_TempDepths.Free();
	PostProcessUtils().m_pCurDepthSurface = NULL;

  SAFE_RELEASE (rd->m_pZBuffer);
  SAFE_RELEASE(rd->m_RP.m_MSAAData.m_pZBuffer);
  SAFE_RELEASE (rd->m_pBackBuffer);
  SAFE_RELEASE(rd->m_pSecondBackBuffer);

#if defined(ENABLE_RENDER_AUX_GEOM)
	if (rd->m_pRenderAuxGeomD3D)
		rd->m_pRenderAuxGeomD3D->ReleaseDeviceObjects();
#endif

	if( PostEffectMgr() )
		PostEffectMgr()->OnLostDevice();

	assert( rd->m_nRTStackLevel[0] == 0 );
	while( 0 < rd->m_nRTStackLevel[0] )
	{
		rd->FX_PopRenderTarget(0);
	}
  rd->PostDeviceReset();
  //if (rd->m_pStereoRenderer)
  //  rd->m_pStereoRenderer->Shutdown();
}



//--------------------------------------------------------------------------------------
// Release D3D9 resources created in the OnD3D9CreateDevice callback 
//--------------------------------------------------------------------------------------
void CALLBACK CD3D9Renderer::OnD3D9DestroyDevice(void* pUserContext)
{
}

#ifndef XENON
bool CALLBACK CD3D9Renderer::OnD3D9DeviceChanging(DXUTDeviceSettings* pDeviceSettings, void* pUserContext)
{
  IDirect3D9 * pD3D9 = DXUTGetD3D9Object();
  if (pD3D9 != NULL && CV_d3d9_nvperfhud)
  {
		for (UINT Adapter=0; Adapter < pD3D9->GetAdapterCount(); Adapter++)
		{
			D3DADAPTER_IDENTIFIER9 Identifier;
			HRESULT Res=pD3D9->GetAdapterIdentifier(Adapter,0,&Identifier);
			if (strstr(Identifier.Description,"PerfHUD") != 0)
			{
				OutputDebugString( TEXT("Opting in to nvPerfHUD!\n"));

				pDeviceSettings->d3d9.AdapterOrdinal=Adapter;
				pDeviceSettings->d3d9.DeviceType=D3DDEVTYPE_REF;
				pDeviceSettings->d3d9.BehaviorFlags &= ~D3DCREATE_PUREDEVICE;
				pDeviceSettings->d3d9.BehaviorFlags |= D3DCREATE_MULTITHREADED;

				break;
			}
		}
  }
  return true;
}
#endif

HRESULT CALLBACK CD3D9Renderer::OnD3D9PostCreateDevice(D3DDevice *pd3dDevice)
{
  CD3D9Renderer *rd = gcpRendD3D;
#ifndef XENON
  DXUTDeviceSettings* pDev = DXUTGetCurrentDeviceSettings();

  rd->m_pD3D = DXUTGetD3D9Object();
  rd->m_pd3dDevice = DXUTGetD3D9Device();
  rd->m_pd3dCaps = DXUTGetD3D9DeviceCaps();
  rd->m_pd3dpp = &pDev->d3d9.pp;

#if CAPTURE_REPLAY_LOG
	rd->MemReplayWrapD3DDevice();
#endif
#endif

  // DXUT doesn't create a device when started from Media Center (DEVICE_LOST) but returns S_OK in DXUTCreateDevice() 
  // call above! Shouldn't happen as we call SuccessfullyLaunchFromMediaCenter() to wait until a device can be created 
  // again but if that fails too check for a NULL pointer here to prevent crashes
  if (!rd->m_pD3D || !rd->m_pd3dDevice) 
    return S_FALSE;

  return S_OK;
}

#elif defined (DIRECT3D10) && defined(USE_DXUT)

//--------------------------------------------------------------------------------------
// Reject any D3D10 devices that aren't acceptable by returning false
//--------------------------------------------------------------------------------------
bool CALLBACK CD3D9Renderer::IsD3D11DeviceAcceptable( const CD3D11EnumAdapterInfo *AdapterInfo, UINT Output, const CD3D11EnumDeviceInfo *DeviceInfo, DXGI_FORMAT BackBufferFormat, bool bWindowed, void* pUserContext )
{
  return true;
}

bool    CALLBACK CD3D9Renderer::OnD3D11DeviceChanging(DXUTDeviceSettings* pDeviceSettings, void* pUserContext)
{
  if (CV_d3d9_nvperfhud)
  {
    IDXGIFactory *pDXGIFactory = DXUTGetDXGIFactory();
    if (!pDXGIFactory)
      return true;

    // Search for a PerfHUD adapter.  
    UINT nAdapter = 0; 
    IDXGIAdapter* adapter = NULL; 
    int nSelectedAdapter = -1; 
    D3D_DRIVER_TYPE driverType = D3D_DRIVER_TYPE_HARDWARE; 
    bool isPerfHUD = false;

    while (pDXGIFactory->EnumAdapters(nAdapter, &adapter) != DXGI_ERROR_NOT_FOUND) 
    { 
      if (adapter) 
      { 
        DXGI_ADAPTER_DESC adaptDesc; 
        if (SUCCEEDED(adapter->GetDesc(&adaptDesc))) 
        { 
          isPerfHUD = wcscmp(adaptDesc.Description, L"NVIDIA PerfHUD") == 0; 

          // Select the first adapter in normal circumstances or the PerfHUD one if it exists. 
          if(nAdapter == 0 || isPerfHUD) 
            nSelectedAdapter = nAdapter; 

          ++nAdapter; 
        } 
      } 
    }
    if (isPerfHUD)
    {
      pDeviceSettings->d3d11.AdapterOrdinal = nSelectedAdapter;
      pDeviceSettings->d3d11.DriverType = D3D_DRIVER_TYPE_REFERENCE;
      OutputDebugString( TEXT("Opting in to nvPerfHUD!\n"));
    }
  }
  return true;
}
#endif
#ifdef DIRECT3D10
//--------------------------------------------------------------------------------------
// Create any D3D10 resources that aren't dependant on the back buffer
//--------------------------------------------------------------------------------------
HRESULT CALLBACK CD3D9Renderer::OnD3D11CreateDevice( ID3D11Device* pd3dDevice, const DXGI_SURFACE_DESC *pBackBufferSurfaceDesc, void* pUserContext )
{
  CD3D9Renderer *rd = gcpRendD3D;

  rd->m_Features |= RFT_HW_R2VB | RFT_OCCLUSIONQUERY | 
                RFT_ALLOWANISOTROPIC | RFT_HW_SM20 | RFT_HW_SM2X | RFT_HW_SM30 | RFT_HW_SM40;

  rd->m_pd3dDevice = pd3dDevice;
#if CAPTURE_REPLAY_LOG
	rd->MemReplayWrapD3DDevice();
#endif
#ifdef _DEBUG
	rd->m_d3dDebug.Init(rd->m_pd3dDevice);
	rd->m_d3dDebug.Update(ESeverityCombination(CV_d3d10_debugMuteSeverity->GetIVal()), CV_d3d10_debugMuteMsgID->GetString(), CV_d3d10_debugBreakOnMsgID->GetString());
	rd->m_bUpdateD3DDebug = false;
#endif

#if defined(USE_DXUT)
	rd->m_d3dsdBackBuffer = *pBackBufferSurfaceDesc;
	DXUTDeviceSettings* pDev = DXUTGetCurrentDeviceSettings();
	CD3D11Enumeration* pd3dEnum = DXUTGetD3D11Enumeration();
	rd->m_pd3dDeviceContext = DXUTGetD3D11DeviceContext();
	CD3D11EnumAdapterInfo* pAdapterInfo = pd3dEnum->GetAdapterInfo(pDev->d3d11.AdapterOrdinal);

#if defined(WIN32) || defined(WIN64)
	LARGE_INTEGER driverVersion; driverVersion.LowPart = 0; driverVersion.HighPart = 0;
	pAdapterInfo->m_pAdapter->CheckInterfaceSupport(__uuidof(ID3D10Device), &driverVersion);
	iLog->Log ( "D3D Adapter: Description: %ls", pAdapterInfo->AdapterDesc.Description);
	iLog->Log ( "D3D Adapter: Driver version (UMD): %d.%02d.%02d.%04d", HIWORD(driverVersion.u.HighPart), LOWORD(driverVersion.u.HighPart), HIWORD(driverVersion.u.LowPart), LOWORD(driverVersion.u.LowPart));
	iLog->Log ( "D3D Adapter: VendorId = 0x%.4X", pAdapterInfo->AdapterDesc.VendorId);
	iLog->Log ( "D3D Adapter: DeviceId = 0x%.4X", pAdapterInfo->AdapterDesc.DeviceId);
	iLog->Log ( "D3D Adapter: SubSysId = 0x%.8X", pAdapterInfo->AdapterDesc.SubSysId);
	iLog->Log ( "D3D Adapter: Revision = %i", pAdapterInfo->AdapterDesc.Revision);
#endif

	// Vendor-specific initializations and workarounds for driver bugs.
	{
		if(pAdapterInfo->AdapterDesc.VendorId==4098)
		{
			// ATI
      rd->m_Features |= RFT_HW_ATI;
			rd->InitATIAPI();

			iLog->Log ("D3D Detected: ATI video card");
		}
		else if( pAdapterInfo->AdapterDesc.VendorId==4318 )
		{
			rd->m_Features |= RFT_HW_NVIDIA;
			rd->InitNVAPI();

			iLog->Log ("D3D Detected: NVidia video card");
		}
	}
#else // defined(USE_DXUT)
#ifndef gringo
	pd3dDevice->GetImmediateContext(&rd->m_pd3dDeviceContext);
	LPVOID pBackBuf;
	HRESULT hr = rd->m_pSwapChain->GetBuffer( 0, __uuidof(ID3D11Texture2D), &pBackBuf);
	assert(SUCCEEDED(hr));
	ID3D11Texture2D *pBackBuffer = (ID3D11Texture2D*)pBackBuf;
	D3D11_TEXTURE2D_DESC backBufferSurfaceDesc;
	pBackBuffer->GetDesc( &backBufferSurfaceDesc );
	ZeroMemory( &rd->m_d3dsdBackBuffer, sizeof(rd->m_d3dsdBackBuffer) );
	rd->m_d3dsdBackBuffer.Width = (UINT) backBufferSurfaceDesc.Width;
	rd->m_d3dsdBackBuffer.Height = (UINT) backBufferSurfaceDesc.Height;
	rd->m_d3dsdBackBuffer.Format = backBufferSurfaceDesc.Format;
	rd->m_d3dsdBackBuffer.SampleDesc = backBufferSurfaceDesc.SampleDesc;
	SAFE_RELEASE(pBackBuffer);
#endif // #ifndef gringo
#endif // defined(USE_DXUT)

  rd->m_numtmus = 16;
	rd->m_MaxAnisotropyLevel = 16;
  rd->m_MaxAnisotropyLevel = min(rd->m_MaxAnisotropyLevel, CRenderer::CV_r_texmaxanisotropy);

  CTexture::SetDefTexFilter(CV_d3d9_texturefilter->GetString());

#if defined(WIN32) || defined(WIN64)
	HWND hWndDesktop = GetDesktopWindow();
	HDC dc = GetDC(hWndDesktop);
	uint16 gamma[3][256];
	if (GetDeviceGammaRamp(dc, gamma))
		rd->m_Features |= RFT_HWGAMMA;
	ReleaseDC(hWndDesktop, dc);
#endif

  // For safety, lots of drivers don't handle tiny texture sizes too tell.
#if defined(WIN32) || defined(WIN64)
	rd->m_MaxTextureMemory = pAdapterInfo->AdapterDesc.DedicatedVideoMemory;
#else
	rd->m_MaxTextureMemory = 256 * 1024 * 1024;




#endif
  if (CRenderer::CV_r_texturesstreampoolsize <= 0)
    CRenderer::CV_r_texturesstreampoolsize = (int)(rd->m_MaxTextureMemory/1024.0f/1024.0f*0.75f);




  rd->m_MaxTextureSize = 8192;


  rd->m_bDeviceSupportsR16FRendertarget = true;
  rd->m_bDeviceSupportsInstancing = true;
  rd->m_bDeviceSupports_G16R16_MSAA = true;






	rd->m_bDeviceSupportsR2VB = false;
	rd->m_bDeviceSupportsVertexTexture = true;
	rd->m_Features |= RFT_HW_VERTEXTEXTURES;
	rd->m_bDeviceSupports_A2B10G10R10F = true;


  rd->m_Features |= RFT_OCCLUSIONTEST;

	rd->m_bUseWaterTessHW = CV_r_WaterTessellationHW != 0;

  rd->m_bDeviceSupportsFP16Separate = false;




  rd->m_bDeviceSupportsFP16Filter = true;


  // Handle the texture formats we need.
  {
    // Find the needed texture formats.
    {
      rd->m_FirstPixelFormat = NULL;

      // RGB uncompressed unsigned formats
      rd->m_FormatA8R8G8B8.CheckSupport(DXGI_FORMAT_R8G8B8A8_UNORM, "A8R8G8B8");
      rd->m_FormatX8R8G8B8.CheckSupport(DXGI_FORMAT_R8G8B8A8_UNORM, "X8R8G8B8");
      rd->m_FormatR8G8B8.CheckSupport(DXGI_FORMAT_R8G8B8A8_UNORM, "R8G8B8");

      //rd->m_FormatA1R5G5B5.CheckSupport(DXGI_FORMAT_B5G5R5A1_UNORM, "A1R5G5B5");
      rd->m_FormatR5G6B5.CheckSupport(DXGI_FORMAT_B5G6R5_UNORM, "R5G6B5");
      //rd->m_FormatX1R5G5B5.CheckSupport(DXGI_FORMAT_B5G5R5A1_UNORM, "X1R5G5B5");

      // Alpha formats
      rd->m_FormatA8.CheckSupport(DXGI_FORMAT_A8_UNORM, "A8");





      // Fat RGB uncompressed unsigned formats
      rd->m_FormatA16B16G16R16F.CheckSupport(DXGI_FORMAT_R16G16B16A16_FLOAT, "A16B16G16R16F");
      rd->m_FormatA16B16G16R16.CheckSupport(DXGI_FORMAT_R16G16B16A16_UNORM, "A16B16G16R16");
      rd->m_FormatG16R16F.CheckSupport(DXGI_FORMAT_R16G16_FLOAT, "G16R16F");
			rd->m_FormatV16U16.CheckSupport(DXGI_FORMAT_R16G16_SNORM, "V16U16");
			rd->m_FormatR16F.CheckSupport(DXGI_FORMAT_R16_FLOAT, "R16F");
      rd->m_FormatR32F.CheckSupport(DXGI_FORMAT_R32_FLOAT, "R32F");
      rd->m_FormatA32B32G32R32F.CheckSupport(DXGI_FORMAT_R32G32B32A32_FLOAT, "A32B32G32R32F");

      // RGB compressed unsigned formats
      rd->m_FormatDXT1.CheckSupport(DXGI_FORMAT_BC1_UNORM, "DXT1");
      rd->m_FormatDXT3.CheckSupport(DXGI_FORMAT_BC2_UNORM, "DXT3");
      rd->m_FormatDXT5.CheckSupport(DXGI_FORMAT_BC3_UNORM, "DXT5");
      rd->m_Format3Dc.CheckSupport(DXGI_FORMAT_BC5_UNORM, "3DC");

      // Depth formats
      rd->m_FormatDepth24.CheckSupport(DXGI_FORMAT_D24_UNORM_S8_UINT, "D24S8");
      rd->m_FormatDepth16.CheckSupport(DXGI_FORMAT_D16_UNORM, "D16");

      rd->m_FormatD32F.CheckSupport(DXGI_FORMAT_R32_TYPELESS, "D32F");
      rd->m_FormatD24S8.CheckSupport(DXGI_FORMAT_R24G8_TYPELESS, "D24S8");
      rd->m_FormatD16.CheckSupport(DXGI_FORMAT_R16_TYPELESS, "D16");

      if (rd->m_FormatDXT1.IsValid() || rd->m_FormatDXT3.IsValid() || rd->m_FormatDXT5.IsValid())
        rd->m_Features |= RFT_COMPRESSTEXTURE;
    }
  }

  rd->m_HDR_FloatFormat_Scalar = eTF_R32F;
	int nHDRSupported = 1;
/* 
  if (!nHDRSupported)
  {
  #ifdef USE_HDR
    CV_r_HDRRendering = 0;
  #endif
    rd->m_Features &= ~RFT_HW_HDR;
  }
  else
*/
    rd->m_Features |= RFT_HW_HDR;

  iLog->Log(" Renderer HDR_Scalar: %s", CTexture::NameForTextureFormat(rd->m_HDR_FloatFormat_Scalar));

  rd->m_nHDRType = nHDRSupported;

#if defined(WIN32) || defined(WIN64)
	rd->m_pRT->RC_SetViewport(0, 0, rd->m_width, rd->m_height);
#else
  rd->RT_SetViewport(0, 0, rd->m_width, rd->m_height);
#endif
  rd->m_MainViewport.nX = 0;
  rd->m_MainViewport.nY = 0;
  rd->m_MainViewport.nWidth = rd->m_width;
  rd->m_MainViewport.nHeight = rd->m_height;

  return S_OK;
}
#endif
#if defined (DIRECT3D10)
#if defined(USE_DXUT)
//--------------------------------------------------------------------------------------
// Create any D3D10 resources that depend on the back buffer
//--------------------------------------------------------------------------------------
HRESULT CALLBACK CD3D9Renderer::OnD3D11ResizedSwapChain( ID3D11Device* pd3dDevice, IDXGISwapChain *pSwapChain, const DXGI_SURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext )
{
  return S_OK;
}
#endif

HRESULT CALLBACK CD3D9Renderer::OnD3D10PostCreateDevice(ID3D11Device* pd3dDevice)
{
  CD3D9Renderer *rd = gcpRendD3D;
  HRESULT hr;

  rd->m_pd3dDevice = pd3dDevice;
#if CAPTURE_REPLAY_LOG
	rd->MemReplayWrapD3DDevice();
#endif
#if defined(USE_DXUT)
	rd->m_pd3dDeviceContext = DXUTGetD3D11DeviceContext();
  rd->m_pBackBuffer = DXUTGetD3D11RenderTargetView();
  rd->m_pZBuffer = DXUTGetD3D11DepthStencilView();
  rd->m_ZFormat = DXUTGetCurrentDeviceSettings()->d3d11.AutoDepthStencilFormat;
  rd->m_pSwapChain = DXUTGetDXGISwapChain();
	rd->m_DepthBufferOrig.pTex = DXUTGetD3D11DepthStencil();
	rd->m_DepthBufferOrigMSAA.pTex = DXUTGetD3D11DepthStencil();

  LPVOID pBackBuf;
  hr = rd->m_pSwapChain->GetBuffer( 0, __uuidof(ID3D11Texture2D), &pBackBuf );
  assert(SUCCEEDED(hr));
  ID3D11Texture2D *pBackBuffer = (ID3D11Texture2D*)pBackBuf;	
  D3D11_TEXTURE2D_DESC backBufferSurfaceDesc;
  pBackBuffer->GetDesc( &backBufferSurfaceDesc );
  ZeroMemory(&rd->m_d3dsdBackBuffer, sizeof(rd->m_d3dsdBackBuffer));
  rd->m_d3dsdBackBuffer.Width = (UINT) backBufferSurfaceDesc.Width;
  rd->m_d3dsdBackBuffer.Height = (UINT) backBufferSurfaceDesc.Height;
  rd->m_d3dsdBackBuffer.Format = backBufferSurfaceDesc.Format;
  rd->m_d3dsdBackBuffer.SampleDesc = backBufferSurfaceDesc.SampleDesc;
  SAFE_RELEASE(pBackBuffer);
#else // defined(USE_DXUT)
#ifndef gringo
	pd3dDevice->GetImmediateContext(&rd->m_pd3dDeviceContext);
	LPVOID pBackBuf;
	hr = rd->m_pSwapChain->GetBuffer( 0, __uuidof(ID3D11Texture2D), &pBackBuf );
	assert(SUCCEEDED(hr));
	ID3D11Texture2D *pBackBuffer = (ID3D11Texture2D*)pBackBuf;	
	hr = rd->m_pd3dDevice->CreateRenderTargetView( pBackBuffer, NULL, &rd->m_pBackBuffer );
	assert(SUCCEEDED(hr));
	D3D11_TEXTURE2D_DESC backBufferSurfaceDesc;
  pBackBuffer->GetDesc( &backBufferSurfaceDesc );
	ZeroMemory( &rd->m_d3dsdBackBuffer, sizeof(rd->m_d3dsdBackBuffer) );
	rd->m_d3dsdBackBuffer.Width = (UINT) backBufferSurfaceDesc.Width;
	rd->m_d3dsdBackBuffer.Height = (UINT) backBufferSurfaceDesc.Height;
	rd->m_d3dsdBackBuffer.Format = backBufferSurfaceDesc.Format;
	rd->m_d3dsdBackBuffer.SampleDesc = backBufferSurfaceDesc.SampleDesc;

	ID3D11Texture2D* pDepthStencil = NULL;
	D3D11_TEXTURE2D_DESC descDepth;
	descDepth.Width = backBufferSurfaceDesc.Width;
	descDepth.Height = backBufferSurfaceDesc.Height;
	descDepth.MipLevels = 1;
	descDepth.ArraySize = 1;
	descDepth.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
	descDepth.SampleDesc.Count = 0;
	descDepth.SampleDesc.Quality = 0;
	descDepth.Usage = D3D11_USAGE_DEFAULT;
	descDepth.BindFlags = D3D11_BIND_DEPTH_STENCIL;
	descDepth.CPUAccessFlags = 0;
	descDepth.MiscFlags = 0;
	hr = rd->m_pd3dDevice->CreateTexture2D( &descDepth, NULL, &pDepthStencil );
	assert(SUCCEEDED(hr));

	// Create the depth stencil view
	D3D11_DEPTH_STENCIL_VIEW_DESC descDSV;
	descDSV.Format = descDepth.Format;
	descDSV.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
	descDSV.Texture2D.MipSlice = 0;
	hr = rd->m_pd3dDevice->CreateDepthStencilView( pDepthStencil, &descDSV, &rd->m_pZBuffer );

	rd->m_pd3dDevice->OMSetRenderTargets( 1, &rd->m_pBackBuffer, rd->m_pZBuffer );

	rd->m_ZFormat = descDepth.Format;
	rd->m_DepthBufferOrig.pTex = pDepthStencil;
	rd->m_DepthBufferOrigMSAA.pTex = pDepthStencil;
#endif // #ifndef gringo
#endif // defined(USE_DXUT)

	rd->m_width = rd->m_d3dsdBackBuffer.Width;
	rd->m_height = rd->m_d3dsdBackBuffer.Height;
	rd->m_CVWidth->Set(rd->m_width);
	rd->m_CVHeight->Set(rd->m_height);

  rd->m_nRTStackLevel[0] = 0;
  rd->m_RTStack[0][0].m_pDepth = rd->m_pZBuffer;
  rd->m_RTStack[0][0].m_pSurfDepth = &rd->m_DepthBufferOrig;
  rd->m_RTStack[0][0].m_pTarget = rd->m_pBackBuffer;
  rd->m_RTStack[0][0].m_Width = rd->m_d3dsdBackBuffer.Width;
  rd->m_RTStack[0][0].m_Height = rd->m_d3dsdBackBuffer.Height;
  rd->m_RTStack[0][0].m_bScreenVP = true;

  for (int i=0; i<RT_STACK_WIDTH; i++)
  {
    rd->m_pNewTarget[i] = &rd->m_RTStack[i][0];
    rd->m_pCurTarget[i] = rd->m_pNewTarget[0]->m_pTex;
  }

  rd->m_DepthBufferOrig.pSurf = rd->m_pZBuffer;
	rd->m_pZBuffer->AddRef();
  rd->m_DepthBufferOrig.nWidth = rd->m_d3dsdBackBuffer.Width;
  rd->m_DepthBufferOrig.nHeight = rd->m_d3dsdBackBuffer.Height;
  rd->m_DepthBufferOrig.bBusy = true;
  rd->m_DepthBufferOrig.nFrameAccess = -2;

  rd->m_DepthBufferOrigMSAA.pSurf = rd->m_pZBuffer;
	rd->m_pZBuffer->AddRef();
	rd->m_DepthBufferOrigMSAA.nWidth = rd->m_d3dsdBackBuffer.Width;
  rd->m_DepthBufferOrigMSAA.nHeight = rd->m_d3dsdBackBuffer.Height;
  rd->m_DepthBufferOrigMSAA.bBusy = true;
  rd->m_DepthBufferOrigMSAA.nFrameAccess = -2;

  SAFE_RELEASE(rd->m_RP.m_MSAAData.m_pDepthTex);
  SAFE_RELEASE(rd->m_RP.m_MSAAData.m_pZBuffer);

  rd->CreateMSAADepthBuffer();

  int j;
  rd->m_DynIB.Release();

  for (j=0; j<POOL_MAX; j++)
  {
    rd->m_DynVB[j].Release();
  }

  rd->ReleaseAuxiliaryMeshes();
  rd->CreateAuxiliaryMeshes();
  /*SAFE_RELEASE(rd->m_pUnitFrustumVB);
  SAFE_RELEASE(rd->m_pUnitFrustumIB);

  SAFE_RELEASE(rd->m_pUnitSphereVB);
  SAFE_RELEASE(rd->m_pUnitSphereIB);*/

  D3D11_BUFFER_DESC BufDescI;
  BufDescI.Usage = D3D11_USAGE_DYNAMIC;
  BufDescI.BindFlags = D3D11_BIND_INDEX_BUFFER;
  BufDescI.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
  BufDescI.MiscFlags = 0;

  D3D11_BUFFER_DESC BufDescV;
  ZeroStruct(BufDescV);
  BufDescV.Usage = D3D11_USAGE_DYNAMIC;
  BufDescV.BindFlags = D3D11_BIND_VERTEX_BUFFER;
  BufDescV.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
  BufDescV.MiscFlags = 0;

  {
    MEMSTAT_CONTEXT(EMemStatContextTypes::MSC_D3D, 0, "D3D Dynamic IndexBuffer");
    hr = rd->m_DynIB.CreateIB(rd->m_pd3dDevice, 65536);
    if (FAILED(hr))
      return hr;
  }
  int reduction = 0; 





  for (j=0; j<POOL_MAX; j++)
  {
    MEMSTAT_CONTEXT(EMemStatContextTypes::MSC_D3D, 0, "D3D Dynamic VertexBuffer");
    int nVertSize, nVerts;
    switch (j)
    {
    case POOL_P3F_COL4UB_TEX2F:
    default:
      nVerts = MAX_DYNVB3D_VERTS>>reduction;
      nVertSize = sizeof(SVF_P3F_C4B_T2F);
      break;
    case POOL_TRP3F_COL4UB_TEX2F:
      nVerts = 32768>>reduction;
      nVertSize = sizeof(SVF_TP3F_C4B_T2F);
      break;
    case POOL_TRP3F_TEX2F_TEX3F:
      nVerts = 4096>>reduction;
      nVertSize = sizeof(SVF_TP3F_T2F_T3F);
      break;
    case POOL_P3F_TEX3F:
      nVerts = 16384>>reduction;
      nVertSize = sizeof(SVF_P3F_T3F);
      break;
    case POOL_P3F_TEX2F_TEX3F:
      nVerts = 1024>>reduction;
      nVertSize = sizeof(SVF_P3F_T2F_T3F);
      break;
    }
    rd->m_DynVB[j].CreateVB(rd->m_pd3dDevice, nVerts, nVertSize);
  }







  rd->m_DevBufMan.Init();

  //PS3HACK
#if !defined(PS3) && !defined(CAFE)
  D3D11_QUERY_DESC QDesc;
  QDesc.Query = D3D11_QUERY_EVENT;
  QDesc.MiscFlags = 0;
  hr = pd3dDevice->CreateQuery(&QDesc, &rd->m_pQuery[0]);
  assert(rd->m_pQuery[0]);
  rd->m_pd3dDeviceContext->End(rd->m_pQuery[0]);
  hr = pd3dDevice->CreateQuery(&QDesc, &rd->m_pQuery[1]);
  rd->m_pd3dDeviceContext->End(rd->m_pQuery[1]);
  assert(rd->m_pQuery[1]);
#endif
  rd->EF_Restore();

  rd->m_bDeviceLost = 0;
  rd->m_pLastVDeclaration = NULL;

#if defined(ENABLE_RENDER_AUX_GEOM)
	if (rd->m_pRenderAuxGeomD3D && FAILED(hr=rd->m_pRenderAuxGeomD3D->RestoreDeviceObjects()))
		return hr;
#endif

	CHWShader_D3D::mfSetGlobalParams();
  //rd->ResetToDefault();

#if defined(DIRECT3D10)



	rd->m_OcclQueries.Reserve(MAX_OCCL_QUERIES);
	for(int a=0;a<MAX_OCCL_QUERIES;a++)
		rd->m_OcclQueries[a].Create();
#endif
  return S_OK;
}

#if defined(USE_DXUT)
//--------------------------------------------------------------------------------------
// Render the scene using the D3D10 device
//--------------------------------------------------------------------------------------
void CALLBACK CD3D9Renderer::OnD3D11FrameRender( ID3D11Device* pd3dDevice, ID3D11DeviceContext* pd3dImmediateContext, double fTime, float fElapsedTime, void* pUserContext )
{
}


//--------------------------------------------------------------------------------------
// Release D3D10 resources created in OnD3D10ResizedSwapChain 
//--------------------------------------------------------------------------------------
void CALLBACK CD3D9Renderer::OnD3D11ReleasingSwapChain( void* pUserContext )
{
}


//--------------------------------------------------------------------------------------
// Release D3D10 resources created in OnD3D11CreateDevice 
//--------------------------------------------------------------------------------------
void CALLBACK CD3D9Renderer::OnD3D11DestroyDevice( void* pUserContext )
{
#ifdef _DEBUG
	gcpRendD3D->m_d3dDebug.Release();
#endif
	CTexture::s_TexStates.clear();
}

#endif	// #if defined(USE_DXUT)
#endif	// DX11
